Java
Set系列集合
特点
- 无序: 存取顺序不一致(无序次数只有一次)
- 不重复:可去除重复
- 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
实现类特点
- HashSet :无序,不重复,无索引
- LinkedHashSet : 有序,不重复,无索引
- TreeSet : 排序,不重复,无索引
Set集合的功能基本上与Collection的API一致
HashSet底层原理
- HashSet集合底层采取哈希表存储的数据
- 哈希表是一种对于增删改查数据都较好的数据结构
哈希表组成
- JDK 8 之前的, 底层使用数组+链表组成
- JDK 8 开始后,底层采用数组+链表+红黑树组成
哈希值
- 是JDK根据对象的地址,按照某种规则算出来的int类型的数值
Object类的API
- public int hashCode(); 返回对象的哈希值
对象的哈希值特电
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的
HashSet1.7版本的原理解析:数组+链表+(结合哈希算法)
NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
-
创建应该默认长度为16的数组,数组名为table
-
根据元素的哈希值跟数组的长度求余计算出应存入的位置(哈希算法)
-
判断当前位置是否为null,表示有元素,则调用equals方法比较
-
如果一样,则不存,如果不一样,则存入数组
- JDK 7新元素占老元素位置,指向老元素
- JDK 8中新元素挂在老元素的下面
结论:哈希表是一种对于增删改查数据性能都较好的结构
JDK 8 版本开始HashSet原理解析
- 底层结构:哈希表(数组,链表,红黑树的结合体)
- 当挂在元素下面的数据过多时,查询性能下降,从JDK8 开始后,当链表长度超过8的时候,自动转换为红黑树
结论:JDK 8 开始后,哈希表对于红黑树的引入进一步提高了操作数据的性能.
JDK 8哈希表的详细流程
- 创建一个默认长度为16,默认加载因为0.75的数组,数组名table
- 根据元素的哈希值跟数组的长度计算出应存入的位置
- 判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数据
- 当数组存满到16*0.75 = 12 时,就自动扩容,每次扩容原先的两倍
HashSet去重复原理解析
- 创建一个默认长度为16的数组,数组名table
- 根据元素的哈希值跟数组的长度求余,计算出应存入的位置(哈希算法)
- 判断当前位置是否为null,如果null直接存入
- 如果位置不为null,表示有元素,则调用equals方法比较
- 如果一样,则不存,如果不一样,则存入数组
结论 : 如果希望Set集合认为2个内容一样的对象重复的,必须重写对象的hashCode()和equals()方法
package com.yu.HashCollection;
import java.util.HashSet;
import java.util.Set;
public class HashStudens {
public static void main(String[] args) {
Set<Student> sets = new HashSet<>();
Student s1 = new Student("余" ,"19","男");
Student s2 = new Student("余" ,"19","男");
Student s3 = new Student("习" ,"20","男");
Student s4 = new Student("xi" ,"21","男");
sets.add(s1);
sets.add(s2);
sets.add(s3);
sets.add(s4);
System.out.println(sets);
}
}
package com.yu.HashCollection;
import java.util.Objects;
import java.util.Set;
public class Student {
private String name;
private String id;
private String sex;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(id, student.id) && Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, id, sex);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
", sex='" + sex + '\'' +
'}';
}
public Student() {
}
public Student(String name, String id, String sex) {
this.name = name;
this.id = id;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
运行结果
[Student{name='xi', id='21', sex='男'}, Student{name='余', id='19', sex='男'}, Student{name='习', id='20', sex='男'}]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix