1. import java.util.HashSet;
  2. class Dog{
  3. String color;
  4. public Dog(String s){
  5. color = s;
  6. }
  7. }
  8. public class SetAndHashCode {
  9. public static void main(String[] args) {
  10. HashSet<Dog> dogSet = new HashSet<Dog>();
  11. dogSet.add( new Dog( "white" ));
  12. dogSet.add( new Dog( "white" ));
  13. System.out.println( "We have " + dogSet.size() + " white dogs!" );
  14. if (dogSet.contains( new Dog( "white" ))){
  15. System.out.println( "We have a white dog!" );
  16. } else {
  17. System.out.println( "No white dog!" );
  18. }
  19. }
  20. }
上述代码的输出为: Set的contains(Object o) 方法详解 Java的API文档指出: 当且仅当 本set包含一个元素 e,并且满足(o==null ? e==null : o.equals(e))条件时,contains()方法才返回true. 因此 contains()方法 必定使用equals方法来检查是否相等. 需要注意的是: set 中是可以包含 null值的(常见的集合类都可以包含null值). 所以如果添加了null,然后判断是否包含null,将会返回true,代码如下所示:
  1. HashSet<Dog> a = new HashSet<Dog>();
  2. a.add( null );
  3. if (a.contains( null )){
  4. System.out.println( "true" );
  5. }
Java的根类Object定义了  public boolean equals(Object obj) 方法.因此所有的对象,包括数组(array,[]),都实现了此方法。 在自定义类里,如果没有明确地重写(override)此方法,那么就会使用Object类的默认实现.即只有两个对象(引用)指向同一块内存地址(即同一个实际对象, x==y为true)时,才会返回true。 如果把Dog类修改为如下代码,能实现我们的目标吗?
  1. class Dog{
  2. String color;
  3. public Dog(String s){
  4. color = s;
  5. }
  6. //重写equals方法, 最佳实践就是如下这种判断顺序:
  7. public boolean equals(Object obj) {
  8. if (!(obj instanceof Dog))
  9. return false ;
  10. if (obj == this )
  11. return true ;
  12. return this .color == ((Dog) obj).color;
  13. }
  14. }
英文答案是: no. 问题的关键在于 Java中hashCode与equals方法的紧密联系 . hashCode() 是Object类定义的另一个基础方法. equals()与hashCode()方法之间的设计实现原则为: 如果两个对象相等(使用equals()方法),那么必须拥有相同的哈希码(使用hashCode()方法). 即使两个对象有相同的哈希值(hash code),他们不一定相等.意思就是: 多个不同的对象,可以返回同一个hash值. hashCode()的默认实现是为不同的对象返回不同的整数.有一个设计原则是,hashCode对于同一个对象,不管内部怎么改变,应该都返回相同的整数值. 在上面的例子中,因为未定义自己的hashCode()实现,因此默认实现对两个对象返回两个不同的整数,这种情况破坏了约定原则。
  1. class Dog{
  2. String color;
  3. public Dog(String s){
  4. color = s;
  5. }
  6. //重写equals方法, 最佳实践就是如下这种判断顺序:
  7. public boolean equals(Object obj) {
  8. if (!(obj instanceof Dog))
  9. return false ;
  10. if (obj == this )
  11. return true ;
  12. return this .color == ((Dog) obj).color;
  13. }
  14. public int hashCode(){
  15. return color.length(); //简单原则
  16. }
  17. }
但是上面的hashCode实现,要求Dog的color是不变的.否则会出现如下的这种困惑:
  1. import java.util.HashSet;
  2. import java.util.Set;
  3. public class TestContains {
  4. public static final class Person{
  5. private String name = "" ;
  6. public Person(String n) {
  7. setName(n);
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setName(String name) {
  13. this .name = (name== null )? "" : name;
  14. }
  15. @Override
  16. public int hashCode() {
  17. // 请考虑是否值得这么做,因为此时name是会变的.
  18. return name.length();
  19. // 推荐让name不可改变
  20. }
  21. @Override
  22. public boolean equals(Object obj) {
  23. if (!(obj instanceof Person)){
  24. return false ;
  25. }
  26. if (obj == this ){
  27. return true ;
  28. }
  29. return this .name.equals(((Person)obj).name);
  30. }
  31. };
  32. public static void main(String[] args) {
  33. Set<Person> persons = new HashSet<Person>();
  34. //
  35. Person person = new Person( "tiemao" );
  36. persons.add(person);
  37. // 修改name, 则依赖hash的集合可能失去作用
  38. person.setName( "ren" );
  39. // 同一个对象,居然是false,原因是我们重写了hashCode,打破了hashCode不变的基本约定
  40. boolean has = persons.contains(person);
  41. int size = persons.size();
  42. System.out.println( "has=" +has); // has=false.
  43. System.out.println( "size=" +size); // size=1
  44. }
  45. }
参考文章: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html

1. Java equals() and hashCode() Contract

2. HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap

3. Java: Find all callers of a method – get all methods that call a particular method

理解Java机制最受欢迎的8幅图 Java中Set的contains()方法 —— hashCode与equals方法的约定及重写原则翻译人员: 铁锚翻译时间: 2013年11月5日原文链接: Java hashCode() and equals() Contract for the contains(Object o) Method of Set本文主要讨论 集合Set 中存储对象的 hashCode 文章目录前言equals 方法 如何编写equals 方法 Object 类是 Java 所有类的始祖, 在 Java 每个类都是由它扩展而来的。如果一个类没有明确地指出其超类,Object 就被认为是这个类的超类(父类)。 equals 方法 在 Object 类 ,equals 方法 将判断两个对象是否具有相同的引用。这与 Java “==”的功能是一样的。换句话说,Object类 的equals 方法 并不会比较对象的内容(状态)。正因为如此,其他类往往需要重写equals 方法 比较对
1.重写equals1.1重写equals原因(1)Object类 equals 方法 比较的是两个对象的引用地址,只有对象的引用地址指向同一个地址时,才认为这两个地址是相等的,否则这两个对象就不想等。 (2)如果有两个对象,他们的属性是相同的,但是地址不同,这样使用equals()比较得出的结果是不相等的,而我们需要的是这两个对象相等,因此默认的equals() 方法 是不符合我们的要求的,这个时候我们就需要对equals() 方法 进行重写以满足我们的预期结果。 (3)在 java 的集合框架 需要用到equals()
因此Hash Set 无序不可重复,也就意味着存放到Hash Set 的对象元素是经过排序比较的。 如何比较呢? 1.HashMap底层是根据hashcode和equals来存放对象的。 2.我们知道Object父类 的hashcode 方法 默认返回的是对象的地址值,因此如果不重写hashcode,那么默认比较的是存放到集合 的对象
详解重写equals和hashcode为什么要重写equals( )怎样重写equals( )自反性原则对称性原则传递性原则为什么要重写hashcode( )怎样重写hashcode( ) 为什么要重写equals( )  判断两个对象在逻辑上是否相等,如根据类的成员变量来判断两个类的实例是否相等,而继承Object 的equals 方法 只能判断两个引用变量是否是同一个对象,这样我们往往需要重写eq...
为什么重写equals时必须重写hashCode 方法 Java 的hash值主要是用来在散列存储结构 确定对象的存储地址的,提高对象的查询效率。 Java 设计的顶级父类Object类 ,有两个 方法 很特殊,它们分别是equals 方法 与hashCode 方法 。——一旦重写了equals 方法 ,就一定要重写hashCode 方法 。以下是Object的源码: public class Object { * Note that it is generally necessary to override th
hashcode 方法 会影响jvm性能?听上去天方夜谭,实际上蕴藏着一些微小的原理,接下来让我们走进hashcode 方法 ,一探native 方法 源头。 默认实现是什么? 调用hashCode 方法 默认返回的值被称为identity hash code(标识哈希码),接下来我们会用标识哈希码来区分重写hashCode 方法 。如果一个类重写了hashCode 方法 ,那么通过调用System.identityHashCode(Object o) 方法 获得标识哈希码。 在hashCode 方法 注释 ,说hashCode一般是通过
关于hashCode和equals的处理,遵循如下规则: 1.只要重写equals 方法 ,就必须要重写hashCode。 2.因为 Set 存储的是不重复的对象,依据hashCode和equals进行判断,所以 Set 存储的对象必须重写这两个 方法 。 3.如果自定义对象作为Map的键,那么必须重写hashCode和equals。 说明:String重写了hashCode和equals 方法 ,所以我们可
hashCode和equals重写 重写hashCode和equals时需注意一点,equals相等则hashCode一定相等(相同对象hash值一致);hashCode相同equals不一定相等(hash值相同不能确定为同一个对象)。所以重写时要保证hashCode的字段和equals的字段相同,否则会导致相同对象有不同的hash值! 重写hashCode Object 的hashCode为native 方法 ,我们对类的hashCode重写本质上只是调用Object 的hashCode进行二次运算,不一定
如果两个对象相等,则 hashcode 一定也是相同的 两个对象相等,对两个对象分别调用 equals 方法 都返回 true 两个对象有相同的 hashcode 值,它们也不一定是相等的 因此,equals 方法 被覆盖过,则 hashCode 方法 也必须被覆盖 hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无...
equals()返利 https://m.cpa5.cn/ equals和hashcode 方法 我们都很了解,是Object类 的定义的 方法 ,这意味着所有的类都隐式实现了这两个 方法 。 Object类 的equals 方法 的默认实现是比较. 哈希值一般用于一定的哈希结构存储 Java hashCode 方法 是定义在Object类内的,也就是说, java 的任何一个对象都有hashCode 方法 ,可以获取当前对象的哈希值; Object类内默认的哈希值是当前对象的空间首地址 十进制展示方式; Java 规定如果两个 java 对象使 在覆盖的时候,必须要遵守它的通用约定。 自反性。对于任何非null的引用值x,x.equals(x)必须返回true 对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。 传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.
我们都知道,在 JAVA 世界 ,万物皆对象。而equals和hashCode这两个 方法 也在Object类里被定义,先来看这两个 方法 在Object里面是如何实现的: 先看equals 方法 : public boolean equals(Object obj) { return (this == obj); equals 方法 实现很简单,就是将某对象拿来和原始对象进行...