zoukankan      html  css  js  c++  java
  • java中重写equals和hashCode方法

    java中重写equals和hashCode方法

    为什么要重写equals和hashCode方法

    1.需要将对象放入HsahMap、HashSet等集合中的类需要重写HashCode和equals()方法:

    Hashcode在基于key-value的集合如:HashMap、LinkedHashMap中扮演很重要的角色。此外在HashSet集合中也会运用到,使用合适的hashcode方法在检索操作时的时间复杂度最好的是 O(1).

    hashCode()和equals()定义在Object类中,这个类是所有Java类的基类,所以所有的java类都继承这两个方法。

    hashCode()方法被用来获取给定对象的唯一整数。这个整数被用来确定对象被存储在HashTable类似的结构中的位置。默认的,Object类的hashCode()方法返回这个对象存储的内存地址的编号。

    参考Josh Bloch的书《Effective Java》,一个好的hashcode方法通常最好是不相等的对象产生不相等的hash值,理想情况下,hashcode方法应该把集合中不相等的实例均匀分布到所有可能的hash值上面。

    补充一个类似的:什么时候类需要实现Serializable接口:当某个类的实体对象需要持久化到硬盘,或通过网络传输数据

    2. 对于对象中的每个域,hashCode值遵循以下原则

    为该域计算int类型的哈希值hc:

    • 如果是boolean类型,计算(f?1:0)
    • 如果是byte、char、short或者int类型,计算(int)f
    • 如果是long类型,计算(int)(f^(f>>>32))
    • 如果是float类型,计算Float.floatToIntBits(f)
    • 如果是double类型,计算Double.doubleToLongBits(f),然后重复第三个步骤。
    • 如果是一个对象引用,并且该类的equals方法通过递归调用equals方法来比较这个域,同样为这个域递归的调用hashCode,如果这个域为null,则返回0。
    • 如果是数组,要把每一个元素当作单独的域来处理,递归的运用上述规则,如果数组域中的每个元素都很重要,那么可以使用Arrays.hashCode方法。

    把上面计算得到的hash值hc合并到result中

    result = result*31 + hc;
    • 1
    • 1

    String中的Hashcode方法 
    String的hashcode的算法就充分利用了字符串内部字符数组的所有字符。生成hash码的算法的在string类中看起来像如下所示,注意“s“是那个字符数组,n是字符串的长度。

    s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
    • 1
    • 1

    eclipse中自动生成Hashcode方法 
    如使用username 和password字段来生成hashCode

    /**
     * 根据userName和password来计算hashCode
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((password == null) ? 0 : password.hashCode());
        result = prime * result + ((userName == null) ? 0 : userName.hashCode());
        return result;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    企业级应用中一般推荐使用第三方库如Apache commons来生成hashocde方法。

    Apache commons HashcodeBuilder 
    我们可以用Apache Commons hashcode builder来生成代码,使用这样一个第三方库的优势是可以反复验证尝试代码。下面代码显示了如何使用Apache Commons hash code 为一个自定义类构建生成hash code 。

    public int hashCode(){
          HashCodeBuilder builder = new HashCodeBuilder();
          builder.append(mostSignificantMemberVariable);
           .......................
          builder.append(leastSignificantMemberVariable);
          return builder.toHashCode();
       }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    equals方法重写

    eclipse中自动生成equals方法 
    如使用username 和password字段来生成equals

        /**
         * 重写equals()方法,只要name、pass相等的员工即可认为相等
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            User other = (User) obj;
            if (password == null) {
                if (other.password != null)
                    return false;
            } else if (!password.equals(other.password))
                return false;
            if (userName == null) {
                if (other.userName != null)
                    return false;
            } else if (!userName.equals(other.userName))
                return false;
            return true;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意以下几点

    • 尽量保证使用对象的同一个属性来生成hashCode()和equals()两个方法。在我们的案例中,我们使用员工id。
    • eqauls方法必须保证一致(如果对象没有被修改,equals应该返回相同的值)
    • 任何时候只要a.equals(b),那么a.hashCode()必须和b.hashCode()相等。
    • 两者必须同时重写。

    当使用ORM的时候特别要注意的

    • 如果你使用ORM处理一些对象的话,你要确保在hashCode()和equals()对象中使用getter和setter而不是直接引用成员变量。因为在ORM中有的时候成员变量会被延时加载,这些变量只有当getter方法被调用的时候才真正可用。
    • 例如在我们的例子中,如果我们使用e1.id == e2.id则可能会出现这个问题,但是我们使用e1.getId() == 
      e2.getId()就不会出现这个问题。
     
    0
  • 相关阅读:
    echarts模拟highcharts实现折线图的虚实转换
    Chrome开发者工具详解 (5):Application、Security、Audits面板
    Chrome 开发者工具详解(4):Profiles 面板
    Chrome开发者工具详解(3):Timeline面板
    Chrome 开发者工具详解(2):Network 面板
    Chrome开发者工具详解(1):Elements、Console、Sources面板
    移动前端开发之 viewport 的深入理解
    响应式图片
    JS中的函数节流
    总结oninput、onchange与onpropertychange事件的用法和区别 书写搜索的神奇代码
  • 原文地址:https://www.cnblogs.com/handsome1013/p/6898507.html
Copyright © 2011-2022 走看看