zoukankan      html  css  js  c++  java
  • 深入理解hashCode

    1、hashCode的概念

    (1)hashCode方法是Object类的方法,在Java里所有类都默认继承Object类,即所有类都有hashCode方法。

    (2)hashCode是jdk根据对象的存储地址算出来的一个int数字,即对象的哈希码值,代表了该对象在内存中的存储地址

    2、hashCode的作用

    2.1、hashCode查找的快捷性

    hashCode的存在主要是用于查找的快捷性,如HashTable、HashMap等,hashCode用来在散列存储结构中确定对象的存储地址(是存储地址)。

    2.2、HashSet不允许重复是如何实现的

    比如,大家都知道HashSet是不允许重复的,HashSet有100个元素了,这时再add一个新元素。

    (1)如果没有hashCode

    就需要迭代100次,调用100次equals方法来判断该HashSet里是否已经存在这个新添加的元素。可想而知,效率是很低的。

    (2)如果有hashCode

    向HashSet添加一个新元素时,HashSet首先会调用hashCode方法,这样就可以定位到它的存储位置,若该处没有元素,则直接保存。如果该处已经有元素存在,就调用equals判断这两个元素内容是否相同,相同则不存,不同则散列到其它位置。这样处理,当我们向HashSet插入大量元素的时候就可以大大减少调用equals方法的次数,提高了效率。

    2.3、HashSet集合和hashCode方法的代码示例

    import java.util.HashSet;
    
    public class Person {
    
        private int id;
        private String name;
        
        public Person(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + id;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            
            //用于查看hashCode方法什么时候被调用,以及被调用的次数
            System.out.println("hashCode被调用, hashCode=" + result);
            
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            
            //用于查看equals方法什么时候被调用,以及被调用的次数
            System.out.println( "equals被调用了" );
            
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Person other = (Person) obj;
            if (id != other.id)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
        
        public static void main(String[] args) {
            HashSet<Person> personHashSet = new HashSet<Person>();
            personHashSet.add(new Person(1, "张三"));
            personHashSet.add(new Person(2, "李四"));
            personHashSet.add(new Person(1, "张三"));
            System.out.println("personHashSet的长度是" + personHashSet.size());
        }
        
    } 
    hashCode被调用, hashCode=775881
    hashCode被调用, hashCode=843084
    hashCode被调用, hashCode=775881
    equals被调用了
    personHashSet的长度是2

    每次向personHashSet添加一个Person时,都会调用hashCode方法,这样就可以直接定位该Person所存储的位置,若该处没有其它Person,则直接保存。若该处已经有Person存在,就调用equals方法来判断两个Person是否相同,相同则不存,不同则散列到其他位置。示例代码里,向personHashSet添加新元素时,hashCode方法无论如何都会被调用,所以hashCode方法被调用了三次。第1个Person和第3个Person的hashCode是相同的,添加第3个Person时才会去调用equals方法,所以equals方法被调用了一次。equals为true,相同则不存,所以personHashSet的长度是2。

    (注:HashSet更详细的解读,会出现在本人后面的博文中,这里就不喧宾夺主本文的主题了。)

    3、hashCode和equals的关系

    (1)equals相等,hashCode一定相等。

    (2)equals方法被重写,那么hashCode方法也应该被重写,并且产生hashCode使用的对象(类里面的属性),一定要和equals方法中使用的一致。

    (3)hashCode相等,equals不一定相等。只能说明这两个对象在散列存储结构里(如Hashtable)“存放在同一个蓝子里”。

  • 相关阅读:
    JAVASCRIPT函数定义表达式和函数声明的区别
    单链表
    Asp.net+jquery+ajaxpro异步仿Facebook纵向时间轴效果
    基于Hadoop开发网络云盘系统客户端界面设计初稿
    U盘安装CentOS 6.4 + Windows 7双系统 (Windows 7下安装 CentOS 6.4)
    Last_SQL_Errno: 1050
    delphi 7中使用idhttp抓取网页 解决假死现象(使用TIdAntiFreezeControl控件)
    继承CWnd自绘按钮
    gcc编译器对宽字符的识别
    解决Qt程序发布时中文乱码问题(通过QApplication.addLibraryPath加载QTextCodec插件)
  • 原文地址:https://www.cnblogs.com/onezg/p/8948767.html
Copyright © 2011-2022 走看看