HashSet去重原理解析

HashSet是基于HashMap实现的,它的去重原理就是利用HashMapkey不能重复的特性。

在HashSet中,元素被存放在HashMap的key中,value则是一个常量对象,所以HashSet能够保证元素的不重复。

当我们向 HashSet 中添加元素时,HashSet 会先调用元素的 hashCode() 方法得到元素的哈希值,然后根据哈希值计算出元素在 HashMap 中的存储位置。如果该位置上已经有元素了,HashSet 会调用该元素的 equals() 方法与新元素进行比较,如果 equals() 方法返回 true,HashSet 就认为这两个元素是相同的,不会将新元素添加进去。如果 equals() 方法返回false,HashSet 就会将新元素添加进去。

但是会存在一些特殊的情况:两个元素的hashCode()相同,但是他们的值不同。例如:

public static void main(String[] args) {
		String a = "通话";
		String b = "重地";
		
		System.out.println(a.hashCode());
		System.out.println(b.hashCode());
		
		System.out.println(a==b);
	}

运行结果为:

我们可以认为在HashSet中通过判断两个元素的hascode() 和 equals()得到的结果是否相同来判断他们是否是同一个值,如果相同,则认为是同一个。

HashSet的泛型是基本类型时,官方已经将基本类型的hascode() 和 equals()重写了,但是在我们自定义的类中却没有,因此,如果我们想要在HashSet的泛型为我们自定义的类型中正确去重,就需要重写元素的hashCode()和equals()方法,使它们能够正确地比较元素的内容。

判断重复的步骤:
        ①: 通过hashcode判断hashcode值是否相同
        ②:如果hashcode的值相同在判断equals是否相同,均相同认为是同一个元素

举个例子:定义一个student类

public class Student {
	private String name;
	private int age;
	
	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

    @Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

设置a和b两个对象,并将其添加进HashSet集合set中

public static void main(String[] args) {
		Student a = new Student("张飞", 25);
		Student b = new Student("张飞", 25);
		HashSet<Student> set = new HashSet<Student>();
		System.out.println(set.add(a));
		System.out.println(set.add(b));
		System.out.println(a.hashCode());
		System.out.println(b.hashCode());
        System.out.println(set);
	}

运行结果为:

可以看出添加的两个元素的key值相同,value值也相同,按照HashSet的定义因该是不能同时存在于一个集合中的,但是运行后得出的hashCode()值不同,因此都可以添加进set集合中,这个时候,就需要在Student类中重写hascode() 和 equals()方法了。

重写方法后的Student类:

public class Student {
	private String name;
	private int age;
	
	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return Objects.hash(this.name,this.age);
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student student = (Student)obj;
		return Objects.equals(name , student.name);
	}
    
    @Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

再次运行前面添加的a和b元素,得到的结果为:

可以看到再次运行后,第二次在添加相同的元素就添加不进去了,也就达到了我们想要的结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值