前段时间有人问我为什么重写了hashcode(),就必须重写equals(),这时候你就会想这种必然性是肯定存在的吗?那么,重写了equals(),hashcode()有没有必要重写呢?
其实,重不重写hashcode()以及equals()取决于你想用自己生成的对象干什么,以及你想用什么样的结构来存储它。如果你写了一个类,你只是想将该类生成的对象放进ArrayList这样的集合,必要时把它取出来,这时候,你完全没有必要重写hashcode(),对于equals是否要重写,这取决于你的业务需要。如果你要将该类生成的对象放进HashMap这样的哈希结构中,并且将该对象作为key来存储,那么你必须要重写hashcode()和equals()方法。之所以有上述的区别,与sun 对java 中 ArrayList和HashMap的实现有关。(这里拿ArrayList和HashMap来举例说明)。
ArrayList的底层是由数组来实现,当你读取ArrayList中的某个对象时,可以用get(int index),或get(Object ),如果使用get(Object),他将通过调用equals()来比较对象,并返回找到的第一个结果。如果你根据业务需要重写了equals(),那么,返回的对象就是你所需要的对象了,如果每有重写equals,那么将自动调用从Object继承来得equals(),这时候它比较的是对象的地址。
HashMap的实现,我们可以把它看作是个二维数组,只不过每一个一维元素里存放的是个集合。这里hashcode就是一维数组的下标,通过hashcode找到我们需要的对象被存储的集合,然后通过equals()方法和集合中的对象进行比较,来唯一确定我们需要找的对象。所以,当你要将自己的类放进HashMap时,用重写的hashcode()方法来指定我们要将对象放到哪个集合中,我们定义equals方法,是为了在这个集合中能够唯一区分需要添加的对象。
好的hashcode()生成的值尽可能的分散,否则,HashSet或HashMap会在某一块区域内的负载较大。我们生成的hashcode不必唯一,但是通过hashcode和equals能够找到的对象必须唯一。(Thinking in java中好像这样说)
好像通过上面的这些,还可以得出一个结论:两个对象的hashcode相等,并不能说明它们就是同一个对象;两个对象通过equals()比较之后返回true,也不能一定就说他们相等。它们在什么条件下相等,这就和具体的应用有关了,比如在HashMap中存放的两个对象的hashcode相等,他们就可以不是同一个对象,同样,也可以将equals()比较后返回true的两个对象放进不同的hashcode对应的集合中去(实际应用中有人会这么做?)。
我们重写hashcode()以及equals()也和业务逻辑有关,具体情况,就待各位大虾们自己琢磨了。