zoukankan      html  css  js  c++  java
  • HashMap, equals, hashCode

    equals和hashCode是Object类中的两个方法。

    这两个方法会被所有的类继承,也就是说所有的类都有这两个方法。

    这两个方法可以被重写。

    重写equals和hashCode有一个原则:

    如果两个对象是equals的,那么尽量使hashCode相同;

    如果两个对象的hashCode相同,那么这两个对象不一定equals。

    最近有一个人问我一个问题。

    给一个Person类追加了一个equals方法,但是没有重写hashCode方法有没有什么问题?

    当然没有问题了,但是他说是有问题的。问题出在了HashMap这里。如果把这个Person对象作为key放到HashMap中,value暂且不管,会出问题。

    以上是环境。尽管他说的不太对,但是有一定的启发。

    HashMap存在的意义是能够方便的获取某一个key所对应的value。而通过这个key去获取对象的时候会调用这个key的hashCode方法。

    public class HashEqualsTester {
    
        public static void main(String[] args) {
            Person p1 = new Person();
            p1.setId("abc");
            p1.setName("ABC");
            p1.setAge(25);
            p1.setDescription("I am just person 1.");
    
            Person p2 = new Person();
            p2.setId("abc");
            p2.setName("ABC");
            p2.setAge(25);
            p2.setDescription("I am just person 2.");
    
            Map<Person, String> map = new HashMap<Person, String>();
    
            map.put(p1, p1.getDescription());
            map.put(p2, p2.getDescription());
    
        }
    
    }
    
    class Person {
        private String id;
        private String name;
        private Integer age;
        private String description;
    
        @Override
        public int hashCode() {
            System.out.println("hashCode called...");
            return 1;
        }
        // get and set
    }
    

      

    执行main函数,会打印:

    hashCode called...
    hashCode called...

    但是我们打印map的时候,如:

    System.out.println(map);

    执行结果为:

    hashCode called...
    {hash.equals.Person@1=I am just person 2.}

    并且,map中只存在一条记录。也就是说当两个对象的hashCode值相同的时候,只保存一个值。

    如果hashCode不相同呢?

    如果两个对象的hashCode相同,会继续调用对象的equals方法,如果两个对象是equals的,那么也只会在map中存一个值,并且是后一个值。

    把代码放一下:

    package hash.equals;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class HashEqualsTester {
    
        public static void main(String[] args) {
            Person p1 = new Person();
            p1.setId("abc");
            p1.setName("ABC");
            p1.setAge(25);
            p1.setDescription("I am just person 1.");
    
            Person p2 = new Person();
            p2.setId("abc");
            p2.setName("ABC");
            p2.setAge(25);
            p2.setDescription("I am just person 2.");
    
            Map<Person, String> map = new HashMap<Person, String>();
    
            map.put(p1, p1.getDescription());
            map.put(p2, p2.getDescription());
    
            System.out.println(map);
    
            System.out.println(map.get(p1));
            System.out.println(map.get(p2));
    
        }
    
    }
    
    class Person {
        private String id;
        private String name;
        private Integer age;
        private String description;
    
        @Override
        public boolean equals(Object person) {
            System.out.println("equals called...");
            return true;
        }
    
        @Override
        public int hashCode() {
            System.out.println("hashCode called...");
            return 1;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    }

    执行结果:

    hashCode called...
    hashCode called...
    equals called...
    hashCode called...
    {hash.equals.Person@1=I am just person 2.}
    hashCode called...
    I am just person 2.
    hashCode called...
    equals called...
    I am just person 2.

    话虽如此,这里面仍然有几个东西不太明确。

    1,为什么要用一个对象作为map的key呢?

    2,知道了这些有什么意义呢?

    3,有一本java书籍上说过,除非你有很正当的理由,不然别去重写你的equals和hashCode方法。

    =================================

    * Note that it is generally necessary to override the {@code hashCode}
    * method whenever this method is overridden, so as to maintain the
    * general contract for the {@code hashCode} method, which states
    * that equal objects must have equal hash codes.

    这是java官方的equals中的一段描述,如果对equals方法进行了override的话,重写hashCode通常就是必须的了。

    ===============================================================

    重写了equals方法,而不去重写hashcode并没有什么太大的问题,只不过会造成性能低下。 

  • 相关阅读:
    [中文翻译] ASP.NET 5 简介(Introducing ASP.NET 5,原作ScottGu 2015/2/23)
    会写网页 就会写手机APP #2-- 范例修正 , Hybrid Mobile Apps for ASP.NET Developers (Apache Cordova)
    vue事件处理
    vue渲染
    vue数组和对象方法
    vue样式绑定
    vue模板语法与绑定指令
    墨刀的使用
    ajax基础一
    解构赋值中圆括号问题及解构赋值的用途
  • 原文地址:https://www.cnblogs.com/voctrals/p/7586250.html
Copyright © 2011-2022 走看看