==与equals 的区别,为什么重写 equals 方法也要重写 hashCode 方法?

==

  • 引用类型:== 是直接比较的两个对象的堆内存地址,如果相等,则说明两个引用实际是指向同一个对象地址的。

  • 基本类型:对于 基本数据类型(8个)和 String 来说又是怎样呢?

    int a = 123;
    int b = 123;
    System.out.println(a == b);	// true
    
    String s1 = "abc";
    String s2 = "abc";
    System.out.println(s1 == s2);	// true
    
    String s3 = new String("abc");
    System.out.println(s1 == s3);	// false
    

    对于基本类型(8个)和 直接声明的 “abc” 字符串,他们是作为字面量存在常量池中以 HashSet 策略存储起来的,在常量池中,一个常量只会对应一个地址,所以它们的引用都是指向的同一块地址。

  • 另外,对于基本数据的包装类型,除了Float和Double之外,其他的六种都是实现了常量池技术,其中 Integer 在常量池中的存储范围为 [-128,127] ,在这个范围外的值,会在堆内存中创建一个新的对象保存这个值。

equals

  • Object 的通用方法,在没有重写之前,与 == 是没有区别的;

        public boolean equals(Object obj) {
            return (this == obj);
       }
    
  • 而一般 equals 方法是需要我们自行重写的,String 和 基本类型封装类就重写了 equals,从而进行的是内容的比较;

  • 一般实现:

    • public class Student {
          private String num;
          private String name;
      
          @Override
          public boolean equals(Object o) {
              if (this == o) return true;
              if (o == null || getClass() != o.getClass()) return false;
              Student student = (Student) o;
              return Objects.equals(num, student.num) &&
                      Objects.equals(name, student.name);
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(num, name);
          }
      }
      
    • 检查是否为同一个对象的引用,如果是直接返回 true;

    • 检查是否为空,是否同一类型,为空 或 类型不一致,返回 false;

    • 将 Object 对象转型;

    • 判断每个属性的值是否相等

hashCode

  • Object 的通用方法,hashcode是根据对象的内存地址经哈希算法得来的;
  • hashCode 方法主要是为了给 HashMap、HashSet 等集合类使用的。
  • 一些规定:
    • 两个对象相等,hashcode一定相等
    • 两个对象不等,hashcode不一定不等
    • hashcode相等,两个对象不一定相等
    • hashcode不等,两个对象一定不等

为什么重写 equals 方法一定要重写 hashCode 方法?

  • 官方说法:对象的equals方法被重写,那么对象的hashCode()也尽量重写;(主要看应用场景)
  • equals 方法 和 hashCode 方法本身并没有紧密的联系,只是应用场景(如HashMap、HashSet等集合类的存取)使它们出现在了一起,才有了这句话;
  • 哈希集合(如HashMap)要保证元素唯一性。key对象放入集合,先经过hash运算,得到index,找到数组对应位置,还要和此位置的对象进行比较(先用hash比较,后用equals方法),不一样就插入到后面形成链表,一样的话就不用插入了。重写了equals()方法,但不重写hashcode()方法,那可能两个相同的对象放入到了不同的位置,元素的唯一性就不存在了。(HashMap存入键值对的方式要复杂的多,这里只是简要说下)

你可能感兴趣的:(java基础,字符串,java,hashcode,object,javase)