java集合进阶篇-《HashSet和LinkedHashSet详解》
个人主页→VON
收录专栏→java从入门到起飞
目录
编辑
一、前言
二、简要概述
三、Set集合
四、HashSet集合
五、LinkedHashSet集合
一、前言
HashSet集合和LinkHashSet集合都是Set集合的分支集合,语法大致相同。这些众多的集合虽然许多地方都十分相近,但是底层的原理还是大相径庭的。希望大家能够仔细分辨。
二、简要概述
在Java中,Set
是一个不允许包含重复元素的集合。Set
接口是Collection
接口的子接口,它继承了Collection
的所有方法,并且增加了对唯一性元素存储的支持。Set
的主要实现类有以下几种:
HashSet:
- 基于哈希表实现。
- 不保证元素的存储顺序。
- 插入、删除和查找操作的时间复杂度为 O(1),即常数时间。
- 元素可以通过
hashCode()
和equals()
方法来确定其位置。
LinkedHashSet:
- 继承自
HashSet
,但在内部使用了一个双向链表来链接所有的条目。 - 保持元素的插入顺序。
- 通常比
HashSet
慢一点,因为维护了链表的连接关系。
三、Set集合
Set集合的特点
- 无序、不重复、无索引
- Set集合的方法上基本与Collection的API一致
Set集合的实现类特点
- HashSet:无序、不重复、无索引
- LinkedHashSet:有序、不重复、无索引
- TreeSet:可排序、不重复、无索引
package ArrayDemo.SetDemo;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class A01_SetDemo01 {
public static void main(String[] args) {
// 1.创建一个Set集合的对象
Set<String> s = new HashSet<>();
// 2.添加元素
// 如果元素是第一次添加,则可以添加成功,返回true
// 如果元素是第二次添加,则添加失败,返回false
System.out.println(s.add("张"));// true
System.out.println(s.add("李"));// true
System.out.println(s.add("李"));// false
System.out.println(s.add("李"));// false
System.out.println(s);// [张, 李]
// 3.遍历集合
// 增强for遍历
for (String s1 : s) {
System.out.println(s1);
}
// 迭代器遍历
Iterator<String> str = s.iterator();
while(str.hasNext()){
System.out.println(str.next());
}
// Lambda表达式
s.forEach(str1 -> System.out.println(str1));
}
}
四、HashSet集合
Student类在这里就不过多赘述了,直接快速生成就行了。快捷键想必大家也十分熟悉了。
哈希值:
对象的整体表现形式
- 如果没有重写hashCode方法,计算出的哈希值是不同的
- 如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
- 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样
package ArrayDemo.SetDemo;
public class A02_HashSetDemo01 {
public static void main(String[] args) {
// 1.创建对象
Student s1 = new Student("zhang",18);
Student s2 = new Student("zhang",18);
// 2.如果没有重写hashCode方法,计算出的哈希值是不同的
System.out.println(s1.hashCode());// 495053715
System.out.println(s2.hashCode());// 1922154895
// 3.如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
System.out.println(s1.hashCode());// -703165081
System.out.println(s1.hashCode());// -703165081
// 4.但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样
System.out.println("abc".hashCode());// 96354
System.out.println("acD".hashCode());// 96354
}
}
需求:
创建一个存储学生对象的集合,存储多个学生对象
使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
package ArrayDemo.SetDemo;
import java.util.HashSet;
public class A03_HashSetDemo02 {
public static void main(String[] args) {
// 1.创建四个学生对象
Student s1 = new Student("zhang",18);
Student s2 = new Student("wang",18);
Student s3 = new Student("li",18);
Student s4 = new Student("zhang",18);
// 2.创建集合存储学生对象
HashSet<Student> hs1 = new HashSet<>();
HashSet<Student> hs2 = new HashSet<>();
// 3.添加元素(没有重写HashSet)
System.out.println(hs1.add(s1));// true
System.out.println(hs1.add(s2));// true
System.out.println(hs1.add(s3));// true
System.out.println(hs1.add(s4));// true
System.out.println(hs1);// [Student{name = zhang, age = 18}, Student{name = li, age = 18}, Student{name = zhang, age = 18}, Student{name = wang, age = 18}]
// 4.添加元素(重写HashSet)
System.out.println(hs2.add(s1));// true
System.out.println(hs2.add(s2));// true
System.out.println(hs2.add(s3));// true
System.out.println(hs2.add(s4));// false
System.out.println(hs2);// [Student{name = zhang, age = 18}, Student{name = li, age = 18}, Student{name = wang, age = 18}]
}
}
五、LinkedHashSet集合
package ArrayDemo.SetDemo;
import java.util.LinkedHashSet;
public class A04_LinkedHashSetDemo04 {
public static void main(String[] args) {
// LinkedHashSet集合的特点和原理
// 有序、不重复、无索引
// 底层基于哈希表、使用双链表记录添加顺序
// 1.创建四个学生对象
Student s1 = new Student("zhang",18);
Student s2 = new Student("wang",18);
Student s3 = new Student("li",18);
Student s4 = new Student("zhang",18);
// 2.创建集合对象
LinkedHashSet<Student> lhs = new LinkedHashSet<>();
// 3.添加学生对象
System.out.println(lhs.add(s1));// true
System.out.println(lhs.add(s3));// true
System.out.println(lhs.add(s2));// true
System.out.println(lhs.add(s4));// false
System.out.println(lhs);// [Student{name = zhang, age = 18}, Student{name = li, age = 18}, Student{name = wang, age = 18}]
}
}