HashSet集合及LinkedHashSet集合

什么是Set接口?
Set接口继承了Collection接口,Set不允许存储重复的元素,并且Set接口是无序的,没有索引,也就没有带索引的方法。

1、HashSet集合

HashSet集合的特点:
① 不允许存储重复的元素
② 没有索引,没有带索引的方法,也不能使用for循环遍历
③ 是一个无序集合,存储元素和取出元素的顺序可能不一致
④ 底层是一个哈希表结构

哈希值

哈希值是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址),在Object类中的hashCode方法,可以获取对象的哈希值。int hashCode()方法的源码是public native int hashCode()其中native代表该方法调用的是本地操作系统的方法

对象的地址值是对象的hashCode的值的十六进制形式,我们需要注意这个hashCode是逻辑地址,可以覆盖重写,虽然再打印输出对象的地址能相等,但是实际的地址是不相等的,举例说明

public static void main(String[] args) {
	Person p1 = new Person();
	int h1 = p1.hashCode();
	Person p2 = new Person();
	int h2 = p2.hashCode();
	System.out.println(h1);//得到对象p1的逻辑内存地址为1,因为覆盖重写了hashCode方法
	System.out.println(h2);//得到的对象p2的逻辑内存地址为1
	System.out.println(p1==p2);//得到的结果为false,因为实际的物理内存地址并不相等
}

public class Person(){
// 为了方便,只写出覆盖重写的方法
	@override
	public int hashCode() {
		return 1;
	}
}

String类的哈希值

String类重写了Object类的hashCode方法

public static void main(String[] args) {
	String s1 = new String("abc");
	String s2 = new String("abc");
	System.out.println(s1);//String类重写了hashCode方法,s1和s2的逻辑地址相同
	System.out.println(s2);
	System.out.println("重地".hashCode());//显示的逻辑地址为117935
	System.out.println("通话".hashCode());//显示的逻辑地址为117935

"重地"和"通话"的逻辑内存地址相同

哈希表

jdk1.8版本之前哈希表的结构是:数组+链表
jdk1.8版本之后哈希表的结构是:数组+红黑树(为了提高查询速度)

哈希表的特点就是查询速度快
在这里插入图片描述

2、Set集合不允许存储重复元素的原理

以HashSet集合为例

public static void main(String[] args) {
// 创建了HashSet集合对象
	HashSet<String> set = new HashSet<>();
	String s1 = new String("abc");
	String s2 = new String("abc");
	set.add(s1);
	set.add(s2);
	set.add("重地");
	set.add("通话");
	System.out.println(Set);//打印输出的结果是[重地, 通话, abc]
	
}

由上例子可以看出,即使我们存了重复的元素,但是我们打印输出的时候也不会有重复的元素

画图说明

在这里插入图片描述

文字说明:

当我们new HashSet<>();的时候再堆内存中创建了一个哈希表,Set集合在调用add方法的时候,add方法会调用元素的hashCode()方法和equals()方法进行判断存入哈希表中的元素是否重复
set.add(s1)
add方法会调用s1的hashCode方法,用于计算字符串"abc"的哈希值,得出"abc"的哈希值为96354,在集合中找有没有96354这个哈希值的元素,发现没有就会把s1存储到集合中
set.add(s2)
add方法会调用s2的hashCode方法,用于计算字符串"abc"的哈希值,得出"abc"的哈希值为96354,在集合中发现存在哈希冲突(集合中还有别的数据和s2的哈希值相同),紧接着s2会调用equals方法用来和s2哈希值相同的数据进行比较,因为String类重写了equals,能够判断s1和s2的内容是否相同,经过判断的到true,得到两个元素是相同的,那么就不会把s2存入哈希表
set.add(“重地”)
add方法会调用"重地"的hashCode方法,用于计算字符串"重地"的哈希值,得出"重地"的哈希值为1179395,在集合中找有没有1179395这个哈希值的元素,发现没有就会把"重地"存储到集合中
set.add(“通话”)
add方法会调用"通话"的hashCode方法,用于计算字符串"通话"的哈希值,得出"通话"的哈希值为1179395,在集合中发现存在哈希冲突(集合中还有别的数据和"通话"的哈希值相同),紧接着"通话"会调用equals方法用来和"通话"哈希值相同的数据进行比较,因为String类重写了equals,能够判断"通话"和"重地"的内容是否相同,经过判断的到false,得到两个元素是不相同的,那么就会把"通话"存入哈希表

前提是存储的元素必须重写hashCode方法和equals方法用于判断哈希值和内容是否相同

3、HashSet集合存储自定义类型的元素

如果想使用HashSet集合存储自定义类型的元素,那么要保证保存的元素是唯一的,所以我们必须重写hashCode方法和equals方法


LinkedHashSet集合

LinkedHashSet集合的底层是一个哈希表+链表,多了一条链表哟哦关于记录元素的存储顺序,保证元素的有序性,该集合存储的元素不能重复但是是有序的
举例说明

public static void main(String[] args) {
	HashSet<String> set = new HashSet<>();
	set.add("www");
	set.add("abc");
	set.add("abc");
	set.add("kskd");
	System.out.println(set);// 得到的结果是[abc,www,kskd]是一个无序的不重复的集合

	LinkedHashSet<String> linked = new LinkedHashSet<>();
	linked.add("www");
	linked.add("abc");
	linked.add("abc");
	linked.add("kskd");
	System.out.println(linked);// 得到的结果是[www,abc,kskd]是一个有序的不重复的集合
}
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值