黑马程序员技术交流社区

标题: 【成都校区】重写equals方法 [打印本页]

作者: 小刀葛小伦    时间: 2019-12-26 16:21
标题: 【成都校区】重写equals方法
在每个类中,在重写 equals 方法的时侯,一定要重写 hashcode 方法。如果不这样做,你的类违反了 hashCode的通用约定, 这会阻止它在 HashMap 和 HashSet 这样的集合中正常工作。 根据 Object 规范,以下时具体约定。
当无法重写 hashCode 时,所违反第二个关键条款是:相等的对象必须具有相等的哈希码(hash code)
创建一个Point类,有两个成员变量x和y,并重写了equals方法

[JavaScript] 纯文本查看 复制代码
    public class Point {
        private final int x, y;
   
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
   
   
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (!(obj instanceof Point)) return false;
            Point point = (Point) obj;
            return x == point.x && y == point.y;
        }
    }

在main方法中测试一下
[JavaScript] 纯文本查看 复制代码
    public static void main(String[] args) {
          Point p1 = new Point(1, 2);
          Point p2 = new Point(1, 2);
          System.out.println(p1.equals(p2));// true
   
          Map<Point, String> map = new HashMap<>();
          map.put(p1, "p1");
          System.out.println(map.get(p2)); // null
   
      }

你可能觉得 map.get(p2) 应该返回字符串 p1, 但是却返回null, 这是因为Point类并没有重写hashCode方法,导致两个相等的实例p1和p2返回了不同的哈希码,违反了hashCode的约定,put方法把实例p1放到了一个哈希桶(hash bucket)中,但因为p2的哈希码不等于p1的哈希码,所以get方法会从其它哈希桶中去查找。
解决这个方法很简单,只需要重写Point类的hashCode方法。

[JavaScript] 纯文本查看 复制代码
    @Override
    public int hashCode() {
        int result = Integer.hashCode(x);
        result = 31 * result + Integer.hashCode(y);
        return result;
    }

再次测试
[JavaScript] 纯文本查看 复制代码
    public static void main(String[] args) {
          Point p1 = new Point(1, 2);
          Point p2 = new Point(1, 2);
          System.out.println(p1.equals(p2));// true
   
          Map<Point, String> map = new HashMap<>();
          map.put(p1, "p1");
          System.out.println(map.get(p2)); // p1
      }

这次你会发现map.get(p2) 返回的就是字符串p1了, 因为hashCode这个方法会返回一个简单的确定性计算的结果,它的唯一的输入是 Point实例中的两个重要的属性x和y,所以显然相等的 Point实例具有相同的哈希码。
此外Objects 类有一个静态方法,它接受任意数量的对象并为它们返回一个哈希码。这个名为 hash 的方法可以 让你编写一行 hashCode 方法,其质量与根据这个项目中的上面编写的方法相当。

[JavaScript] 纯文本查看 复制代码
    @Override
    public int hashCode() {
            return Objects.hash(x, y);
    }

注意事项
总之,每次重写 equals 方法时都必须重写 hashCode 方法,否则程序将无法正常运行。你的 hashCode 方 法必须遵从 Object 类指定的常规约定,并且必须执行合理的工作,将不相等的哈希码分配给不相等的实例。









欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2