实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
获得对象的哈希码:hashCode 方法。用来确定元素在一维表中的位置。
equals 方法:用来比较 当前位置的一维表的元素,以及以该元素为头节点的链表中的所有的元素的唯一性。
如果将某种类型的对象作为 HashSet 的元素。那么该类型中 需要 重写 hashCode() 方法,和 equals 方法。
hashCode()方法重写的目的:保证相同属性的对象 具有相同的哈希码的值。 保证了在 哈希表中可以遇见,然后再通过 equals 方法比较是否相等,来保证相同的对象避免添加。
为了保证 HashSet 的正常的工作,考虑:
1:如果两个对象通过 euqals 比较是相等的 ,那么两个对象的哈希码的值 是否 必须一样?
euqals 比较相等,说明两个对象的属性完全一致。那么两个对象的哈希码的 值必须一样。
2:如果两个对象的哈希码一致,那么equals 比较是否 必须相等?
不是必须的,通过添加链表实现将相同哈希码值的对象 放到同一个一维数组元素的位置上。
总结:
如何生成对象的哈希码(散列码):
大的基本原则:每一个对象的哈希码应该是均匀的散列在 int 的正数的取值范围内。然后通过一系列的运算,将对象的哈希码控制在一维数组的范围内。
1:Integer 对象的哈希码的值 就是 它的值自身。
2:通常会有一个质数 来参与运算,对象的哈希码 要求和对象的所有的属性相关。
package com.bjsxt.collection0910;
import java.util.HashSet;
public class HashSetTest1 {
public static void main(String[] args) {
HashSet<Student> set = new HashSet<>();
set.add(new Student("小明",21,Gender.male));
set.add(new Student("小明",21,Gender.male));
System.out.println(set);
}
}
class Student{
private String name;
private int age;
private Gender gender;
public Student(String name, int age, Gender gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", gender=" + gender + "]";
}
@Override
public int hashCode() {
System.out.println("Student.hashCode()");
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((gender == null) ? 0 : gender.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
System.out.println("Student.equals()");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (gender != other.gender)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
enum Gender{
male, female
}