探索
equals(一次性搞清楚equals和hashCode)

在程序设计中,有很多的“公约”,遵守约定去实现你的代码,会让你避开很多坑,这些公约是前人总结出来的设计规范。

这2个方法总是被人放在一起讨论。最近在看集合框架,为了打基础,就决定把一些细枝末节清理掉。一次性搞清楚!

public boolean equals(Object obj)

而我们往往需要用equals来判断 2个对象是否等价,而非验证他们的唯一性。这样我们在实现自己的类时,就要重写equals.

自反性: x.equals(x) 一定是true

对称性: x.equals(y) 和 y.equals(x)结果一致

一致性: 在某个运行时期间,2个对象的状态的改变不会不影响equals的决策结果,那么,在这个运行时期间,无论调用多少次equals,都返回相同的结果。

equals编写指导

在第8行,传入的比较对象的引用和this做比较,这样做是为了 save time ,节约执行时间,如果this 和 obj是 对同一个堆对象的引用,那么,他们一定是qeuals 的。

然后,比较2个对象的运行时类,是否为同一个类。不是同一个类,则不equals。getClass返回的是 this 和obj的运行时类的引用。如果他们属于同一个类,则返回的是同一个运行时类的引用。注意,一个类也是一个对象。

它违反了公约中的对称原则。

dog instanceof Animal 得到true

这就会导致

dog.equals(animal) 返回false

2、按照第一种方法实现,那么equals只能比较同一个类的对象,不同类对象永远是false。但这并不是强制要求的。一般我们也很少需要在不同的类之间使用equals。

4、并不总是要将对象的所有字段来作为equals 的评判依据,那取决于你的业务要求。比如你要做一个家电功率统计系统,如果2个家电的功率一样,那就有足够的依据认为这2个家电对象等价了,至少在你这个业务逻辑背景下是等价的,并不关心他们的价钱啊,品牌啊,大小等其他参数。

public int hashCode

对象的散列码是为了更好的支持基于哈希机制的Java集合类,例如 Hashtable, HashMap, HashSet 等。

重写了euqls方法的对象必须同时重写hashCode方法。

如果2个对象通过equals返回false,他们的hashCode返回的值允许相同。(然而,程序员必须意识到,hashCode返回独一无二的散列码,会让存储这个对象的hashtables更好地工作。)

也是说,参与equals函数的字段,也必须都参与hashCode 的计算。

的实现方式。通常也不是最好的实现方式。

细化,下面我们就来看看对hashCode方法的一致约定要求。

第二:通过equals调用返回true 的2个对象的hashCode一定一样。

总结一句话:等价的(调用equals返回true)对象必须产生相同的散列码。不等价的对象,不要求产生的散列码不相同。

在编写hashCode时,你需要考虑的是,最终的hash是个int值,而不能溢出。不同的对象的hash码应该尽量不同,避免hash冲突。

1、定义一个int类型的变量 hash,初始化为 非0 整数,8,17,20随你。

最后把所有的分量都总和起来,注意并不是简单的相加。选择一个倍乘的数字31,参与计算。然后不断地递归计算,直到所有的字段都参与了。

int hash = 7;

hash = 31 * hash + 字段1贡献分量;

hash = 31 * hash + 字段2贡献分量;

.....

return hash;

编写过程中浏览器挂掉了,又重写了一遍,不开心。不过为了写总结,让自己理解,应该的。

英文原文:http://www.javaranch.com/journal/2002/10/equalhash.html


顶一下()     踩一下()

热门推荐

发表评论
0评