日期:2014-05-20  浏览次数:20753 次

请教考题:用对象作为map键时,重写equals和hashcode方法的问题
有这样一道考题:

Given:
2. class Chilis {
3. Chilis(String c, int h) { color = c; hotness = h; }
4. String color;
5. int hotness;
6. public boolean equals(Object o) {
7. if(this == (Chilis)o) return true;
8. return false;
9. }
10. public String toString() { return color + " " + hotness; }
11. }

If instances of class Chilis are to be used as keys in a Map, which are true? (Choose all that
apply.)
A. Without overriding hashCode(), the code will not compile.
B. As it stands, the equals() method has been legally overridden.
C. It’s possible for such keys to find the correct entries in the Map.
D. It’s NOT possible for such keys to find the correct entries in the Map.
E. As it stands, the Chilis class legally supports the equals() and hashCode() contracts.
F. If hashCode() was correctly overridden, it would make retrieving Map entries by key easier.

正确答案是:B C E

它为什么不选F呢?

首先它没有重写hashCode(),我以为重写hashcode()会提高搜索速度,相当于给对象加了个主键,只按主键搜索,而不是一个一个对象去搜索,不是这样么?请高手指点迷津
而且equals()的重写也没有起到真正的作用,只要2个Chillis对象比较,统统返回true。
hashcode scjp map

------解决方案--------------------
你如果不重写hashcode()
java还是会调用自带的hashcode()吧,其原理一样是把字符串定位到某个物理地址上,
而你如果重写的话,效果应该是一样的。
------解决方案--------------------
引用:
重写equals(),必须重写hashcode(),而且它俩必须结果一致。
即equals()的两个对象,hashcode()必须相等,否则,没用。。。


学习了,大多数时候hashcode都是调用父类的,而equals大部分时候都是覆写的。
------解决方案--------------------
引用:
重写equals(),必须重写hashcode(),而且它俩必须结果一致。
即equals()的两个对象,hashcode()必须相等,否则,没用。。。

 仅仅对于HashSet、HashMap之类的哈希表,“equals()的两个对象,hashcode()必须相等,否则,没用”是正确的。
  JDK的所有哈希表均采用拉链法解决哈希冲突,当你调用put()方法的时候,JDK会先算出对象的hashcode(),如果此hashcode对应的链表为空,则会直接插入;否则将遍历整个链表,依次调用已经存在的元素的equals()进行比较;如果equals()==true,则不插入,break;当遍历完整个链表之后,说明这个链表所有对象的equals()==false,把新的对象插入到链表头部。
  如果想使用JDK的哈希表,一般无需重写hashcode,因为Object自带的hashcode做的很好,在数据量不大的情况下,不会有任何冲突,CRUD的复杂度均为O(1)。
  但当数据量非常大时,如:超过千万级,对象的hashcode难免会出现重复;如果数据量更大,则冲突会更加严重,哈希表的CRUD效率将逐渐退化为O(sqrt(N))。此时,你就可以重写hashcode来减少冲突。或者重写compareTo方法,使用TreeMap,对于超大数据量,TreeMap的效率是O(log2N),反而好于HashMap。
  另外,最重要的,不要只从“重写”、“继承”等等肤浅的角度去分析问题,也不要轻信别人的回复(包括我的回复)、甚至ThinkingInJava、Java核心技术的相关解释之后,就把问题丢在一边;调试和分析JDK源码,才是掌握知识的最权威、最直接的方式!
------解决方案--------------------