Java 中HashCode作用
概述
hashCode()
是 Java 中在 Object
类下的一个方法,其主要目的是返回对象的哈希码。哈希码可以看做是一个对象的特征码,不同的对象拥有不同的哈希码,哈希码值是根据对象内容计算而得的 32 位整数。
在 Java 中,哈希码在很多场合都有很重要的作用,例如:
- HashMap、HashSet、Hashtable、WeakHashMap、IdentityHashMap 等数据结构都使用哈希码来确定对象在集合内的位置;
- 当一个对象要被序列化成字节序列时,先计算出对象的哈希码,然后将其写入输出流;
- 当一个对象被作为参数传递给具有 hashCode 参数的算法时,算法可以根据哈希码来优化计算;
- 等等。
在实际编程中,我们有时需要重写对象的 hashCode()
方法,这是因为对于不同的类需要不同的哈希码策略。在接下来的段落中,我们将通过示例来说明哈希码的应用和编写过程。
示例1:使用哈希码定位对象
HashMap
是 Java 中最常使用的 Map 结构,其内部实现是一个键值对列表,查询的时候使用键的哈希值和散列函数来快速定位对象。下面我们将演示存储自定义对象时,必须重写该对象的 hashCode()
方法,否则在 HashMap 内检索该对象将会失败。
public class Student {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Student student = (Student) obj;
return id == student.id && Objects.equals(name, student.name);
}
}
public class Main {
public static void main(String[] args) {
Map<Student, String> map = new HashMap<>();
map.put(new Student(1, "Tom"), "A");
map.put(new Student(2, "Mary"), "B");
map.put(new Student(3, "Mathew"), "C");
System.out.println(map.get(new Student(1, "Tom"))); // 正常输出:A
System.out.println(map.get(new Student(3, "Mathew"))); // 正常输出:C
System.out.println(map.get(new Student(1, "Jerry"))); // 失败输出:null
}
}
可以看到,由于哈希码被正确地重写了,我们可以成功地定位到 Map
内存储的元素,而在没有重写哈希码的情况下,虽然对象的内容相同,但是由于哈希码不同,因此会被判断为不同的对象,查询结果自然也会失败。
示例2:使用哈希码序列化和反序列化对象
使用哈希码可以方便地序列化和反序列化对象,下面我们将演示自定义类的哈希码实现以及使用哈希码序列化和反序列化对象。
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Student student = (Student) obj;
return id == student.id && Objects.equals(name, student.name);
}
}
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student(1, "Tom");
System.out.println(student.hashCode()); // 正常输出:88431941
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(student);
oos.flush();
byte[] bytes = baos.toByteArray();
oos.close();
baos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
Student s2 = (Student) ois.readObject();
ois.close();
bais.close();
System.out.println(s2.hashCode()); // 正常输出:88431941
System.out.println(s2.equals(student)); // 正常输出:true
}
}
可以看到,我们通过实现自定义的 hashCode()
方法,可以成功地序列化和反序列化对象,这是因为哈希码作为一个对象的重要特征,其内容被写入到字节序列中,成功地标识该对象。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 中HashCode作用_动力节点Java学院整理 - Python技术站