== 用来判断两个对象的地址是否相等,如果是基础类型,比较具体值是否相等。
equals 用来比较两个对象是否相等,默认比较的也是内存地址,一般重写该方法,改为比较对象属性,常见基础类型对应引用类型、String 都重写了 equals() 方法,该方法是 Object 类方法,因此任何类都可以重写该方法
equals 重写时需要满足以下特性:
- 自反性:a.equals(a) 永远返回 True
- 对称性:a.equals(b) 和 b.equals(a) 结果相同
- 传递性:a equals b,b equals c ,那么 a equals c 也为 true
- 连续性:对象和方法参数不变时,equals() 返回结果必须一致
一般情况下,equals 重写依据对象属性判断时一定满足上述情况,除了父子类之间:父类 equals 子类为 true 时,子类不一定 equals() 父类为 true。这是由于子类可以向上转型为父类类型,而 Java 父类不能向下转型。
不满足特性时,在集合使用时可能产生问题,集合中的 contains() 方法基于 equals 实现,假如 obj1 和 obj2 不满足对称性,集合中含有 obj1 时,contains(obj1) 或者 contails(obj2) 都返回 true,而只包含 obj2 时,可能 contails(obj2) 才返回 true
除了 contails(),集合中的查询操作也基于 equals() 实现,如果 equals() 有问题,就可能导致判重,删除都出问题。
hashcode() 也是 Object 方法,通过它获取对象的 hash 值,一般用于哈希集合中。哈希集合每次添加元素时,首先根据该方法计算散列值,确定该元素保存在哪个散列,删除和查询同理。
采用 hash 值区分散列的好处在于提高效率,哈希集合中的元素分配的越均匀,整体查询效率越高。该值默认根据对象地址计算。
在哈希中判断元素是否存在时,首先根据 hashcode() 确定散列,确定散列之后才依次调用 equals(),所以一般重写 equals() 方法还需要重写 hashcode() 方法,两者遵循以下约定:
- equals() 相等,hashcode() 一定相等
- equals() 不相等,hashCode() 可能相等
翻译过来也就是说,相等的对象必须分配到一个散列,否则哈希集合在不同散列会保存相同的元素。分配到相同散列的元素可以不相等