HashSet、TreeSet、LinkedHashSet的区别
HashSet、TreeSet、LinkedHashSet的区别
1、HashSet
1.实现方式:基于哈希表(HashMap)实现
2.不允许重复,可以有一个null元素
3.不保证顺序恒久不变
4.添加元素时把元素作为HashMap的key存储,HashMap的value使用一个固定的Object对象
5.排除重复元素是通过equals来判断元素是否相同
6.判断两个对象是否相同,先判断两个对象的hashCode是否相同(如果两个对象的hashcode相同,不一定是同一个对象,如果不同,那一定不是同一个对象),如果不同,则两个对象不是同一个对象,如果相同还要进行equals判断,equals相同则是同一个对象,不同则不是同一个对象
7.自定义对象要重写hashcode方法和equals对象
小结:
(1)哈希表的存储结构:数组加链表,数组里的每个元素以链表的形式存储
(2)如何把对象存储到哈希表中,先计算对象的hashCode值,再对数组的长度求余数,来决定对象要存储在数组中的哪个位置
(3)解决hashSet中的重复值使用的方式是,参考第6点
基本使用:
写一个实体类(重新equals和hashcode方法)
class Cat {
private String name;
private int age;
private int id;
public Cat(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
// get,set,toString()
// 需要重写hashcode()和equals()方法
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Cat cat = (Cat) o;
return age == cat.age && id == cat.id && name.equals(cat.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, id);
}
}
使用HashSet:
private static void hashSet() {
Set<String> set = new HashSet<>();
set.add("飞飞");
set.add("亮亮");
// 不可重复
set.add("亮亮");
set.add("关关");
set.add("曹操");
set.add("备备");
set.add(null);
set.add(null);
String[] strings = set.toArray(new String[]{});
for (String s : strings
) {
System.out.println(s);
}
Cat c1 = new Cat("miaomiao", 4, 1);
Cat c2 = new Cat("huahua", 3, 2);
Cat c3 = new Cat("tom", 5, 3);
// 需要重写hashcode()方法和equals方法
Cat c4 = new Cat("tom", 5, 3);
Set<Cat> cats = new HashSet<>();
cats.add(c1);
cats.add(c2);
cats.add(c3);
cats.add(c4);
//cats.add(c4);
System.out.println(cats.size());
}
2、TreeSet
1、有序的,基于TreeMap(二叉树数据结构),对象需要比较大小,通过对象比较器来实现
2、对象比较器还可以用来去除重复元素,如果自定义的类,没有实现比较器接口,将无法添加到TreeSet集合中
基本使用:
*/
private static void treeSet() {
Cat c1 = new Cat("miaomiao", 4, 1);
Cat c2 = new Cat("huahua", 3, 2);
Cat c3 = new Cat("tom", 5, 3);
Cat c4 = new Cat("Tom", 4, 1);
//指定排序规则,先按照id,再年龄,再姓名
Set<Cat> cats = new TreeSet<>((o1, o2) -> {
if (o1.getId() != o2.getId()) {
return o1.getId() - o2.getId();
}
if (o1.getAge() != o2.getAge()) {
return o1.getAge() - o2.getAge();
}
return o1.getName().compareTo(o2.getName());
});
cats.add(c1);
cats.add(c2);
cats.add(c3);
cats.add(c4);
System.out.println(cats);
}
3、LinkedHashSet
1、哈希表和链表列表来实现
2、维护着一个运行与所有条目的双重链表列表,此链表定义了迭代顺序,即按照将元素插入到set中的顺序(插入顺序)进行迭代
简单使用:
private static void linkedHashSet(){
Cat c1 = new Cat("miaomiao", 4, 1);
Cat c2 = new Cat("huahua", 3, 2);
Cat c3 = new Cat("tom", 5, 3);
Cat c4 = new Cat("Tom", 4, 1);
Set<Cat> cats = new LinkedHashSet<>();
cats.add(c1);
cats.add(c2);
cats.add(c3);
cats.add(c4);
System.out.println(cats);
}
4、如何选择?
如果要排序,选择TreeSet
如果不要排序,也不要保证顺序,选择HashSet
如果不要排序,要保证顺序,选择LinkedHashSet
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!