• 学习:重写hashCode()方法的必要性


    当一个类有可能会和其他类发生比较的时候,我们会重写equals方法,但大多数情况下,都忽略了重写hashCode方法。

    这里说一下重写hashCode的必要性。

    当我们使用HashSet或者HashMap的时候,在比对value|key是否存在时,会调用hashCode方法。

    注意,hashSet的contains方法其实是依赖于HashMap的containsKey方法的。

    我们来看下containsKey方法的实现:

      public boolean containsKey(java.lang.Object paramObject)
      {
        return (getEntry(paramObject) != null);
      }
    
      final Entry<K, V> getEntry(java.lang.Object paramObject)
      {
        int i = (paramObject == null) ? 0 : hash(paramObject.hashCode());
        Entry localEntry = this.table[indexFor(i, this.table.length)];
        for (; localEntry != null; 
          localEntry = localEntry.next)
        {
          if (localEntry.hash == i) { java.lang.Object localObject;
            if (((localObject = localEntry.key) == paramObject) || ((paramObject != null) && (paramObject.equals(localObject))))
            {
              return localEntry; } }
        }
        return null;
      }

    由上面代码即可知,hashCode是重要的判断依据,没有重写hashCode,equals表现相等的两个类,它们的hashCode并不相等。

    所以会导致containsKey方法返回false,测试代码如下:

    包含HashCode的类:

    package hashset.and.hashcode;
    
    public class ClassWithHashCode {
        public int i;
    
        public boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof ClassWithHashCode) {
                ClassWithHashCode code = (ClassWithHashCode) o;
                return code.i == i;
            }
            return false;
        }
    
        public int hashCode() {
            return i * 17 + 37;
        }
    }

    没有重写hasCode的类:

    package hashset.and.hashcode;
    
    public class ClassWithoutHashCode {
        public int i;
    
        public boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof ClassWithoutHashCode) {
                ClassWithoutHashCode code = (ClassWithoutHashCode) o;
                return code.i == i;
            }
            return false;
        }
    }

    测试类:

    package hashset.and.hashcode;
    
    import java.util.HashSet;
    
    public class Test {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            ClassWithHashCode c1 = new ClassWithHashCode();
            ClassWithHashCode c2 = new ClassWithHashCode();
            c1.i = 0;
            c2.i = 0;
    
            HashSet<ClassWithHashCode> set = new HashSet<ClassWithHashCode>();
            set.add(c1);
            System.out.println(set.contains(c2));
    
            ClassWithoutHashCode co1 = new ClassWithoutHashCode();
            ClassWithoutHashCode co2 = new ClassWithoutHashCode();
            co1.i = 0;
            co2.i = 0;
    
            HashSet<ClassWithoutHashCode> set1 = new HashSet<ClassWithoutHashCode>();
            set1.add(co1);
            System.out.println(set.contains(co2));
        }
    }

    执行的结果为:

    true
    false

    符合预期。证毕。

  • 相关阅读:
    网页素材收集
    【转】你离顶尖 Java 程序员,只差这11本书的距离
    Jetbrains 破解 2017
    WebStorm的常用操作
    浅谈MySQL主从复制
    Lombok注解指南
    【我的《冒号课堂》学习笔记】设计模式(3)行为模式
    【我的《冒号课堂》学习笔记】设计模式(2)结构模式
    【我的《冒号课堂》学习笔记】设计模式(1)创建模式
    【我的《冒号课堂》学习笔记】设计原则(4)保变原则
  • 原文地址:https://www.cnblogs.com/anrainie/p/2473196.html
Copyright © 2020-2023  润新知