欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA - 【为什么要重写hashCode和equals?】HashSet

程序员文章站 2024-03-25 22:06:34
...

JAVA_VERSION="14"
JAVA_VERSION_DATE="2020-03-17"


引入:

在用户自定义类中,重写equals是为了灵活的比较自定义类,而不是使用继承Object类的equals方法;

为什么不直接使用Object类的equals方法,因为Object类的equals方法底层比较采用的是==,而==针对引用类型比较的是地址值(无意义):

JAVA - 【为什么要重写hashCode和equals?】HashSet

那为什么要重写hashCode方法呢?



1> HashSet使用测试(String类与自定义Student类)

package kyleeo.util01;

import java.util.HashSet;

public class HushMapDemo {

	public static void main(String[] args) {
		HashSet<String> set = new HashSet<String>();
		set.add("aaaa");
		set.add("bbbb");
		set.add("aaaa");
		set.add("cccc");
		for(String i:set) {
			System.out.println(i);
		}
		
		HashSet<Student> set2 = new HashSet<Student>();
		set2.add(new Student("aaa",15));
		set2.add(new Student("aaa",14));
		set2.add(new Student("aaa",15));
		set2.add(new Student("bbb",21));
		for(Student i:set2) {
			System.out.println(i.getName()+"---"+i.getAge());
		}
	}
	
}

结果:

aaaa
bbbb
cccc
aaa---15
aaa---15
bbb---21
aaa---14

为什么HashSet集合中存储自定义类型Student的时候不能做到唯一添加呢?

因为添加使用到add方法,继续查看源码中add方法的实现:

JAVA - 【为什么要重写hashCode和equals?】HashSet

继续进入put:

JAVA - 【为什么要重写hashCode和equals?】HashSet

此处可以看到HashSet在进行添加底层使用到了hash方法,而hash值的获取实际上是在hashCode基础上的一系列操作,

在上述框中:

首先会判断待添加数据hash值与原数据hash值是否一致,String类型因为重写了hashCode所以内容一致的String的hashCode也一致,自定义类型由于没有重写hashCode,用的是从Object继承下来的hashCode,而这个hashCode针对不同对象具有不同值;

所以针对自定义类型,上述框中重复比较第一条一直不通过(为false),与后面条件&&后依旧为false,无法再进行验证!

JAVA - 【为什么要重写hashCode和equals?】HashSet

至此,对于自定义类需要手动实现hashCode,hash值一致后还会调用equals再次进行检测,判断内容是否一致;

为什么还要用equals比较呢?因为hash值毕竟只是一个逻辑值,不同的对象有几率出现相同的hash值。

自定义hashCode和equals之后:

JAVA - 【为什么要重写hashCode和equals?】HashSet

( 可以使用eclipse自动生成该类对应的hashCode方法和equals方法 )

自定义Student类:

package kyleeo.util01;

public class Student {
	private String name;
	private int age;
	
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		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 (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

附加:

HushSet没有特殊方法,一般使用Collection中的基本方法。

JAVA - 【为什么要重写hashCode和equals?】HashSet

 

JAVA - 【为什么要重写hashCode和equals?】HashSet

相关标签: JAVA