java集合框架之HashSet类

1.Set是Collection子接口

模拟了数学上的集的概念。

-----------------------------------------------------------------------
Set集合存储特点:
     1):不允许元素重复.
     2):不会记录元素的先后添加顺序.

-----------------------------------------------------------------------

Set只包含从Collection继承的方法,不过Set无法记住添加的顺序不允许包含重复的元素。当试图添加两个相同元素进Set集合,添加操作失败,add()方法返回false。

import java.util.HashSet;
import java.util.Set;

public class SetDemo2 {
	public static void main(String[] args) {
		Set<String> set = new HashSet<>();
		set.add("小明");
		set.add("小红");
		set.add("小张");
		set.add("小明");//和第一个是同一个对象,所以不能添加
		
		System.out.println(set.size());//3
		System.out.println(set);//打印结果:[小张, 小明, 小红],不会记录添加顺序
	}
}

Set判断两个对象是否相等用equals,而不是使用==。也就是说两个对象equals比较返回true,Set集合是不会接受这个对象的

HashSet是Set接口最常用的实现类,顾名思义,底层才用了哈希表(散列/hash)算法.
其底层其实也是一个数组,存在的意义是提供查询速度,插入速度也比较快,但是适用于少量数据的插入操作.

HashSet类是线程不安全的类,在多线程环境下想要保证线程安全.
HashSet set = Collections.synchronizedSet(new HashSet(...));

在HashSet中如何判断两个对象是否相同问题:
       1):两个对象的equals比较相等.   返回true,则说明是相同对象.
       2):两个对象的hashCode方法返回值相等.

对象的hashCode值决定了在哈希表中的存储位置.
二者:缺一不可.
当往HashSet集合中添加新的对象的时候,先回判断该对象和集合对象中的hashCode值:
                         1):不等: 直接把该新的对象存储到hashCode指定的位置.
                         2):相等: 再继续判断新对象和集合对象中的equals做比较.
                                        1>:hashCode相同,equals为true: 则视为是同一个对象,则不保存在哈希表中.
                                        1>:hashCode相同,equals为false:非常麻烦,存储在之前对象同槽为的链表上(拒绝,操作比较麻烦).



对象的hashCode和equals方法的重要性:
每一个存储到hash表中的对象,都得提供hashCode和equals方法,用来判断是否是同一个对象.
存储在哈希表中的对象,都应该覆盖equals方法和hashCode方法,并且保证equals相等的时候,hashCode也应该相等.通过源码可以看到,String类,Integer等8大基本类型包装类都已经覆盖equals方法和hashCode方法,有了自己的判断方式,所以可以直接使用.

如果需要把我们自定义的对象存储到哈希表中,该类型的对象应该覆盖equals和hashCode方法,并在该方法中提供自己的判断规则.可以使用Eclipse工具自动生成hashCode和equals方法.





生成之后就是下面这样:

class Person{
	private int id;
	private int age;
	private String name;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		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 + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (id != other.id)
			return false;
		return true;
	}
}

你可以根据自己的需求来选择判断的条件

举个例子:我们就根据id来决定Person是同一个对象,根据上面的步骤生成根据id来判断的hashCode和equals方法,然后测试添加,注意,Set集合是根据这两个方法一起来判断的,缺一不可

import java.util.HashSet;
import java.util.Set;
//Person类
class Person{
	private int id;
	private int age;
	private String name;
	
	public Person() {
		super();
	}
	public Person(int id, int age, String name) {
		super();
		this.id = id;
		this.age = age;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}	
	@Override
	public String toString() {
		return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
	}
	
	//hashCode方法
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	//equals方法
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (id != other.id)
			return false;
		return true;
	}
}
//测试类
public class SetDemo1 {
	public static void main(String[] args) {
		Person p1 = new Person(0, 18, "张三");
		Person p2 = new Person(1, 18, "李四");//与p1相比年龄相同,姓名,id不同
		Person p3 = new Person(2, 19, "张三");//与p1相比姓名相同,年龄,id不同
		Person p4 = new Person(3, 18, "张三");//与p1相比年龄和姓名都相同,但是id不同
		Person p5 = new Person(0, 19, "王五");//与p1相比id相同,只要id相同就是同一个对象,上面我们已经定义了
		
		Set<Person> set = new HashSet<>();
		set.add(p1);
		set.add(p2);
		set.add(p3);
		set.add(p4);
		set.add(p5);//添加失败,因为是同一个对象
		
		System.out.println(set.size());//只添加了4个,因为第5个和第一个相同
		System.out.println(set);//打印结果[Person [id=3, age=18, name=张三], Person [id=1, age=18, name=李四], Person [id=2, age=19, name=张三], Person [id=0, age=18, name=张三]]
		//可以看到打印结果跟添加顺序不一样,说明Set集合不会记录添加顺序
	}
}

对象的hashCode计算公式




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值