Project 1: Data Structures
Project 1: Data Structures
类值的相等判断永远用.equals()而不是==
花了近两天的时间终于是把Probject 1 完成了,完成了LinkedListDeque和ArrayDeque两种实现的Deque。在此就不再赘述数据结构的实现方法,代码地址
那么我要写一些什么呢?写一些我遇到的问题和bug。
这个bug实在是令人火大,这本是不应该出现的错误
正如二级标题所说的,类值的相等判断永远用.equals()而不是==。而且值得铭记的是,测试文件一定要扩大数据规模,因为扩大规模真的会发现意想不到的错误。
事情的起因是public boolean equals(Object o)这个函数,对于一个自己实现的数据类,这个方法是很有Override的必要的。因为两种数据类基本一样,这里我只用LinkedListDeque举例。
1 | /** |
上面代码是有bug的,我写的时候这种是真的很难注意到。你有可能也没有注意到,接下来是get()函数的实现:
1 | /** |
到这里其实就已经能看清楚问题所在了,get()函数返回的是类型T,是任意封装类,并不是基础数据类型。众所周知Java在比对类是否相等时,==操作符默认是比对类的地址是否一致,也就是看对方是否是自己。显然我们并不想这么做,我们需要比对的是内部存储的值是否相等。就像十张百元钞票和另外十张百元钞票,都是一千元,代表的价值是相同的,而不是因为钞票编号不同所以表示这两堆钞票是不相等的。
相信学习过CS61B课程的同学都已经有了写测试代码的好习惯。我也是如此,但是很遗憾的是尽管我写了junit测试,也并没有查出来这个bug。以下是我一开始写的测试代码:
1 |
|
是的,测试很容易的通过了。这是为什么呢?这里就要引入大名鼎鼎的IntegerCache了。
IntegerCache是Java中的一个类,它是用于缓存Integer对象的一个内部类。在Java中,由于Integer是不可变对象,一些整数值在一定范围内是经常使用的,为了提高性能和节省内存,Java使用了IntegerCache来缓存一些常用的整数对象。
在Java中,对于数值在[-128, 127]范围内的Integer对象,如果通过自动装箱的方式创建,会直接使用IntegerCache中已经存在的对象,而不是每次创建新的对象。这样做可以避免频繁创建新的Integer对象,提高了性能和节省了内存。
例如,当你通过Integer.valueOf()方法创建一个整数值在[-128, 127]范围内的Integer对象时,如果该值在IntegerCache中已经存在,则直接返回缓存中的对象,而不会创建新的对象。
但是需要注意的是,这种缓存机制只适用于整数值在[-128, 127]范围内的情况,超出这个范围的整数值仍然会创建新的Integer对象。
因为IntegerCache的原因,虽然我向两个Deque分别塞入了Ingeter 1,但是实际上这两个1地址是一样的,编号一样的钞票真的不是假钞吗😂
所以正确的测试应该扩大数据规模:
1 |
|
这样因为数据超过了128,显然以前的代码是无法通过这个代码的。在这里贴出修改后正确的代码:
1 |
|
直接调用T本身的equals()方法即可,这样即使还是通不过测试的话那也不是咱们代码的错了。
style 问题
这个Project 1还挺有意思的,实现完数据类后还要用自己写的数据类去弹吉他。但是在此项目中,code 的 style 有严格的要求,第一次交代码的时候一共 640 points 因为 style 没有按照要求竟然扣了大约 84 points,。。。。
但是大可不必阅读那长长的 style 要求,只需要把 IDEA 的自动格式化代码打开即可。具体位置是Settings -> Tools -> Actions on Save -> Reformat code。






