我救自己万万次,铮铮劲草,绝不动摇
—— 24.6.2
一、Set集合介绍
Set和Map密切相关的
Map的遍历需要先变成单列集合,只能变成set集合
二、HashSet集合的介绍和使用
1.概述
HashSet是Set接口的实现类
2.特点
a、元素唯一
b、元素无序
c、无索引
d、线程不安全
3.数据结构:哈希表
a、jdk8之前:哈希表 = 数组 + 链表
b、jdk8之后:哈希表 = 数组 + 链表 + 红黑树
加入红黑树的目的:查询速度快
4.方法
和collection一样
5.遍历
a、增强for
b、迭代器
package S87Set; import java.util.HashSet; import java.util.Iterator; public class Demo241HashSet { public static void main(String[] args) { HashSet<String> set = new HashSet<>(); set.add("张三"); set.add("李四"); set.add("王五"); set.add("赵六"); set.add("田七"); // 读取顺序无序 System.out.println(set); // 遍历 增强for for (String s : set) { System.out.println(s); } System.out.println("——————————————————————————"); // 迭代器 Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } }
三、LinkedHashSet的介绍以及使用
1.概述
LinkedHashSet extends HashSet
2.特点
a、元素唯一
b、元素有序
c、无索引
d、线程不安全
3.数据结构
哈希表 + 双向链表
4.使用
和HashSet一样
package S87Set; import java.util.Iterator; import java.util.LinkedHashSet; public class Demo242LinkedHashSet { public static void main(String[] args) { LinkedHashSet<String> set = new LinkedHashSet<>(); set.add("张三"); set.add("李四"); set.add("王五"); set.add("赵六"); set.add("田七"); // 读取顺序无序 System.out.println(set); // 遍历 增强for for (String s : set) { System.out.println(s); } System.out.println("——————————————————————————"); // 迭代器 Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } }
四、哈希值
1.概述:
是由计算机算出来的一个十进制数,可以看做是对象的地址值
2.获取对象的哈希值,使用的是object中的方法
public native int hashcode()
3.注意:
如果重写了hashcode方法,那计算的就是对象内容的哈希值了
如果不重写hashcode方法,默认计算对象的哈希值
五、字符串的哈希值如何计算出来
直接跑到stringLatin1.hashcode(value)底层源码,
计算abc的哈希值 —> 0xff这个十六进制对应的十进制255任何数据和255做&运算,都是原值
第一圈:
h=31*0+97 =97
第二圈:
h=31*97+98 = 3105
第三圈:
h=31*3105+99=96354
问题:在计算哈希值的时候,有一个定值就是31,为啥?
31是一个质数,31这个数通过大量的计算,统计,认为用31,可以尽量降低内容不一样但是哈希值一样的情况
内容不一样,哈希值一样(哈希冲突,哈希碰撞)
六、HashSet的存储去重复的过程
1.先计算元素的哈希值(重写hashCode方法),在比较内容(重写equals方法)
2.先比较哈希值,如果哈希值不一样,存储
3.如果哈希值一样,再比较内容
a.如果哈希值一样,内容不一样,存
b.如果哈希值一样,内容也一样,去重复package S88Hash; import java.util.HashSet; public class Demo244HashTest { public static void main(String[] args) { HashSet<Object> set = new HashSet<>(); set.add("abc"); set.add("通话"); set.add("重地"); set.add("abc"); System.out.println(set); // [通话, 重地, abc] } }
七、Hashset存储自定义类型如何去重复
1.如果Hashset存储自定义类型,如何去重复呢?重写hashcode和equals方法,让Hashset比较属性的哈希值以及属性的内容
2.如果不重写hashcode和equals方法,默认调用的是object中的,不同的对象,肯定哈希值不一样,equals比较对象的地址值也不一样,所以此时即使对象的属性值一样,也不能去重复