Fork me on GitHub

equals()和hashCode()

原文链接

默认情况下,Java超类java.lang.Object提供了两种比较对象的重要方法:equals()hashCode()。在大型项目中实现多个类之间的交互时,这些方法变得非常有用。在本文中,我们将讨论这些方法之间的关系,它们的默认实现以及强制开发人员为每个方法提供自定义实现的情况。

方法定义和默认实现

1
2
3
4
5
6
7
8
9
public class Object {
...
public boolean equals(Object obj) {
return (this == obj);
}
...
public native int hashCode();
...
}
  • equal()方法:JDK提供的默认实现是基于内存位置的 - 当且仅当它们存储在同一个内存地址中时,两个对象是相等的。
  • hashCode()方法:默认实现是个本地方法。需要满足三个约定:(1) 无论什么时间,在同一个应用内执行多次应该返回相同的值。(2) 如果两个对象的equals()方法返回true,那么它们的hashCode()必须相同。(3) 如果两个对象的equals()方法返回false,那么它们的hashCode()可以相同,也可以不同。

重写equals()

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.programmer.gate.beans;

public class Student {
private int id;
private String name;
public Student(int id, String name) {
this.name = name;
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1
2
3
4
5
6
7
8
9
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof Student))
return false;
if (obj == this)
return true;
return this.getId() == ((Student) obj).getId();
}

equals() With ArrayList

1
2
3
4
5
6
7
8
9
public class HashcodeEquals {
public static void main(String[] args) {
Student alex = new Student(1, "Alex");
List < Student > studentsLst = new ArrayList < Student > ();
studentsLst.add(alex);
System.out.println("Arraylist size = " + studentsLst.size());
System.out.println("Arraylist contains Alex = " + studentsLst.contains(new Student(1, "Alex")));
}
}

以上代码输出为:

1
2
Arraylist size = 1
Arraylist contains Alex = true

原因是ArrayListcontains()方法内部是调用的对象的equals()方法。

重写hashCode()

1
2
3
4
@Override
public int hashCode() {
return id;
}

equals() With HashSet

1
2
3
4
5
6
7
8
9
10
11
public class HashcodeEquals {
public static void main(String[] args) {
Student alex1 = new Student(1, "Alex");
Student alex2 = new Student(1, "Alex");
HashSet < Student > students = new HashSet < Student > ();
students.add(alex1);
students.add(alex2);
System.out.println("HashSet size = " + students.size());
System.out.println("HashSet contains Alex = " + students.contains(new Student(1, "Alex")));
}
}

以上代码输出为:

1
2
HashSet size = 1
HashSet contains Alex = true

HashSet将其元素存储在内存桶中。每个桶都链接到一个特定的哈希码。当调用students.add(alex1)时,Java在存储桶中存储alex1并将其链接到alex1.hashCode()的值。现在任何时候,一个具有相同散列码的元素被插入到集合中,它将会替换掉alex1。但是,由于alex2具有不同的散列码,它将被存储在一个单独的存储桶中,并被视为完全不同的对象。

现在,当HashSet在其中搜索一个元素时,它首先生成元素的哈希码并查找与这个哈希码对应的一个桶。

这同样适用于HashMapHashTable或任何使用散列机制来存储元素的数据结构。hashCode()用于散列到桶,equals()用于判断对象是否相同。

求鼓励,求支持!