目录
- 前言
- 一、常用Set
- 1.1 Set
- 1.1.1 特点
- 1.2 HashSet
- 1.2.1 特点
- 1.2.2 使用
- 1.3 TreeSet
- 1.3.1 特点
- 1.3.2 使用
- 1.4 LinkedHashSet
- 1.4.1 特点
- 1.4.2 使用
- 二、对比总结
目录
前言
一、常用Set
1.1 Set
Set是一个继承自Collection的接口:
public interface Set<E> extends Collection<E> {
Set接口包含Collection接口的所有方法。
api | 作用描述 |
---|---|
add() | 将指定的元素添加到集合中 |
addAll() | 将指定集合的所有元素添加到集合中 |
iterator() | 返回一个迭代器,该迭代器可用于顺序访问集合中的元素 |
remove() | 从集合中移除指定的元素 |
removeAll() | 从存在于另一个指定集合中的集合中删除所有元素 |
keepAll() | 保留集合中所有还存在于另一个指定集合中的所有元素 |
clear() | 从集合中删除所有元素 |
size() | 返回集合的长度(元素数) |
toArray() | 返回包含集合中所有元素的数组 |
contains() | 如果集合包含指定的元素,则返回true |
containsAll() | 如果集合包含指定集合的所有元素,则返回true |
hashCode() | 返回哈希码值(集合中元素的地址) |
Set集合的实现类主要为HashSet、TreeSet、LinkedHashSet等。
1.1.1 特点
Set集合的特点是:
不允许重复元素。
不保证元素的顺序,取决于具体实现类。
基于哈希表或红黑树等数据结构实现。
1.2 HashSet
HashSet是基于哈希表实现的Set集合,不允许重复元素。它通过哈希算法将元素存储在内部的哈希表中,提供了快速的查找和插入操作。
public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, java.io.Serializable
1.2.1 特点
HashSet的特点
不允许重复元素。
不保证元素的顺序,取决于哈希算法和具体实现。
具有常数时间复杂度(O(1))的查找、插入和删除操作。
适用于需要快速查找元素且不关心顺序的场景。
内部使用HashMap实现,元素存储在键的位置,值为一个静态的Object对象。
1.2.2 使用
public static void main(String[] args) {//使用HashSet类创建集合Set<Integer> set1 = new HashSet<>();//将元素添加到set1set1.add(2);set1.add(3);System.out.println("Set1: " + set1);//使用HashSet类创建另一个集合Set<Integer> set2 = new HashSet<>();//添加元素set2.add(1);set2.add(2);System.out.println("Set2: " + set2);//两个集合的并集set2.addAll(set1);System.out.println("并集是: " + set2);}
输出:
1.3 TreeSet
TreeSet是基于红黑树实现的Set集合,可以按照元素的自然顺序或自定义顺序进行排序。它提供了有序的遍历能力,支持高效的插入、删除和查找操作。
public class TreeSet<E> extends AbstractSet<E>implements NavigableSet<E>, Cloneable, java.io.Serializable
1.3.1 特点
TreeSet的特点:
元素按照自然顺序或自定义顺序排序。
提供有序的遍历能力。
查找、插入和删除操作的时间复杂度为O(log n)。
适用于需要有序访问元素的场景。
1.3.2 使用
public static void main(String[] args) {//使用TreeSet类创建集合Set<Integer> numbers = new TreeSet<>();// 将元素添加到set集合numbers.add(2);numbers.add(3);numbers.add(1);System.out.println("TreeSet: " + numbers);//使用iterator()访问元素System.out.print("使用iterator()访问元素: ");Iterator<Integer> iterate = numbers.iterator();while(iterate.hasNext()) {System.out.print(iterate.next());System.out.print(", ");}}
输出:可以看到TreeSet对元素进行了排序
1.4 LinkedHashSet
LinkedHashSet是HashSet的子类,它在HashSet的基础上通过双向链表维护了元素的插入顺序,因此可以保持元素的插入顺序。在需要保持元素插入顺序的场景,同时又需要HashSet的快速查找特性的情况下,使用LinkedHashSet是一个不错的选择。
public class LinkedHashSet<E>extends HashSet<E>implements Set<E>, Cloneable, java.io.Serializable {
1.4.1 特点
LinkedHashSet的特点:
保持插入顺序或访问顺序。
继承了HashSet的查找效率。
具有HashSet的不允许重复元素的特性。
适用于需要保持元素插入顺序的场景。
1.4.2 使用
//具有8个容量和0.75负载因子的LinkedHashSet
LinkedHashSet<Integer> numbers = new LinkedHashSet<>(8, 0.75);
capacity - 该哈希集的容量为8。意味着,它可以存储8个元素。
此哈希集的负载因子为0.75。这意味着,只要我们的哈希表填充了75%,元素就会移动到新哈希表中,该哈希表的大小是原始哈希表的两倍。
并集demo
public static void test1() {LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>();evenNumbers.add(2);evenNumbers.add(4);System.out.println("LinkedHashSet1: " + evenNumbers);LinkedHashSet<Integer> numbers = new LinkedHashSet<>();numbers.add(1);numbers.add(3);System.out.println("LinkedHashSet2: " + numbers);//两个集合的并集numbers.addAll(evenNumbers);System.out.println("并集: " + numbers);}
输出:
交集demo
public static void test2() {LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>();primeNumbers.add(2);primeNumbers.add(3);System.out.println("LinkedHashSet1: " + primeNumbers);LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>();evenNumbers.add(2);evenNumbers.add(4);System.out.println("LinkedHashSet2: " + evenNumbers);//集合的交集evenNumbers.retainAll(primeNumbers);System.out.println("集合的交集: " + evenNumbers);}
输出
LinkedHashSet常用API:
api | 作用描述 |
---|---|
boolean add(E e) | 向集合中添加指定元素。 |
void addAll(Collection<? extends E> c) | 将指定集合中的所有元素添加到集合中。 |
boolean remove(Object o) | 从集合中删除指定元素。 |
void clear() | 清空集合中的所有元素。 |
boolean contains(Object o) | 判断集合中是否包含指定元素。 |
boolean isEmpty() | 判断集合是否为空。 |
int size() | 返回集合中元素的个数。 |
Iterator iterator() | 返回一个迭代器,用于遍历集合中的元素。 |
forEach(Consumer<? super E> action) | 对集合中的每个元素执行指定操作。 |
void clear() | 清空集合中的所有元素。 |
Object clone() | 复制集合。 |
boolean retainAll(Collection<?> c) | 仅保留集合中包含在指定集合中的元素。 |
LinkedHashSet与HashSet的区别
LinkedHashSet在内部维护一个链表。因此,它保持其元素的插入顺序。
LinkedHashSet类比HashSet需要更多的存储空间。这是因为LinkedHashSet在内部维护链表。
LinkedHashSet的性能比HashSet慢。这是因为LinkedHashSet中存在链表。
LinkedHashSet 与TreeSet的区别
TreeSet类实现了SortedSet接口。这就是为什么树集中的元素是有序的。但是,LinkedHashSet类只维护其元素的插入顺序。
TreeSet通常比LinkedHashSet慢。这是因为每当将元素添加到TreeSet时,它都必须执行排序操作。
LinkedHashSet允许插入空值。但是不能向TreeSet插入空值。
二、对比总结
Set | 特点 | 适用场景 |
---|---|---|
HashSet | 基于哈希表实现,不保证元素的顺序。 | 适用于需要快速查找元素且不关心顺序的场景。 |
TreeSet | 基于红黑树实现,元素按照自然顺序或自定义顺序排序。 | 适用于需要有序访问元素的场景,提供了有序的遍历能力。 |
LinkedHashSet | 基于哈希表和双向链表实现,保持插入顺序或访问顺序。 | 适用于需要保持插入顺序或访问顺序的场景,提供了可以预测的迭代顺序。 |
参考链接:
Java LinkedHashSet
Java Set 接口