Java LinkedHashSet类

Java LinkedHashSet

原文: https://howtodoinjava.com/java/collections/java-linkedhashset/

Java LinkedHashSet类扩展了HashSet和实现了Set接口。 除了提供可预测的迭代顺序以外,它与HashSet类非常相似。

Table of Contents

1\. LinkedHashSet Hierarchy
2\. LinkedHashSet Features
3\. LinkedHashSet Constructors
4\. LinkedHashSet Methods
5\. LinkedHashSet Example
6\. LinkedHashSet Usecases
7\. LinkedHashSet Performance
8\. Conclusion

1. LinkedHashSet层次结构

LinkedHashSet类扩展了HashSet类并实现了Set接口。 Set接口以层次结构顺序继承CollectionIterable接口。

public class LinkedHashSet<E> extends HashSet<E> 
				implements Set<E>, Cloneable, Serializable 
{
	//implementation
}

LinkedHashSet Hierarchy

LinkedHashSet层次结构

2. LinkedHashSet特性

  • 它扩展了HashSet类,扩展了AbstractSet类。
  • 它实现了Set接口。
  • LinkedHashSet中不允许重复的值
  • LinkedHashSet中允许一个NULL元素。
  • 这是一个有序集合,这是元素插入到集合中的顺序(插入顺序)。
  • HashSet一样,此类为基本操作(添加,删除,包含和调整大小)提供恒定时间性能
  • LinkedHashSet未同步。 如果多个线程同时访问哈希集合,并且至少有一个线程修改了哈希集合,则必须在外部对其进行同步。
  • 使用Collections.synchronizedSet(new LinkedHashSet())方法来获取同步的LinkedHashSet
  • 此类的迭代器方法返回的迭代器为快速失败,并且如果在创建迭代器后的任何时间修改了集合,则可能会抛出ConcurrentModificationException,除了通过迭代器自己的remove()方法之外 。
  • LinkedHashSet还实现了SearlizableCloneable接口。

2.1 初始容量

初始容量是指创建LinkedHashSet时的存储桶数(在支持HashMap中)。 如果当前大小已满,则存储桶数将自动增加。

默认初始容量为 16 。 我们可以通过在构造器 LinkedHashSet(int initialCapacity)中传递默认容量来覆盖此默认容量。

2.2 负载系数

负载因子是在自动增加LinkedHashSet的容量之前允许其充满的度量。 默认负载系数为 0.75

这称为阈值,等于(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY)。 当LinkedHashSet元素计数超过此阈值时,将调整LinkedHashSet的大小,并且新容量是先前容量的两倍。

使用默认的LinkedHashSet时,内部容量为 16,负载系数为 0.75。 当表格中有 12 个元素时,存储桶数将自动增加。

3. LinkedHashSet构造器

LinkedHashSet具有四种构造器:

  1. LinkedHashSet():使用默认的初始容量(16)和负载因子(0.75)初始化默认的LinkedHashSet实例。
  2. LinkedHashSet(int Capacity):使用指定的容量和负载因子(0.75)初始化LinkedHashSet
  3. LinkedHashSet(int Capacity, float loadFactor):使用指定的初始容量和负载因子初始化LinkedHashSet
  4. LinkedHashSet(Collection c):使用与指定集合相同的元素初始化LinkedHashSet

4. LinkedHashSet方法

  1. public boolean add(E e):如果指定的元素尚不存在,则将其添加到Set中。 此方法在内部使用 equals()方法检查重复项。 如果元素重复,则元素被拒绝,并且不替换值。
  2. public void clear():从LinkedHashSet中删除所有元素。
  3. public boolean contains(Object o):如果LinkedHashSet包含指定的元素则返回true,否则为false
  4. public boolean isEmpty():如果LinkedHashSet不包含任何元素,则返回true,否则返回false
  5. public int size():返回LinkedHashSet中的元素数。
  6. public Iterator<E> iterator():在此LinkedHashSet中的元素上返回迭代器。 从迭代器返回的元素没有特定的顺序。
  7. public boolean remove(Object o):从LinkedHashSet中删除指定的元素(如果存在)并返回true,否则返回false
  8. public boolean removeAll(Collection <?> c):删除LinkedHashSet中属于指定集合的​​所有元素。
  9. public Object clone():返回LinkedHashSet的浅表副本。
  10. public Spliterator<E> spliterator():在此LinkedHashSet中的元素上创建后绑定和快速失败的Spliterator。 它具有以下初始化属性Spliterator.DISTINCTSpliterator.ORDERED

5. LinkedHashSet示例

5.1 LinkedHashSet添加,删除,迭代器示例

//1\. Create LinkedHashSet
LinkedHashSet<String> LinkedHashSet = new LinkedHashSet<>();

//2\. Add elements to LinkedHashSet 
LinkedHashSet.add("A");
LinkedHashSet.add("B");
LinkedHashSet.add("C");
LinkedHashSet.add("D");
LinkedHashSet.add("E");

System.out.println(LinkedHashSet);

//3\. Check if element exists
boolean found = LinkedHashSet.contains("A");        //true
System.out.println(found);

//4\. Remove an element
LinkedHashSet.remove("D");

//5\. Iterate over values
Iterator<String> itr = LinkedHashSet.iterator();

while(itr.hasNext()) 
{
    String value = itr.next();

    System.out.println("Value: " + value);
}

程序输出。

[A, B, C, D, E]
true
Value: A
Value: B
Value: C
Value: E

5.2 将LinkedHashSet转换为数组示例

Java 示例,使用toArrray()方法将LinkedHashSet转换为数组。

LinkedHashSet<String> LinkedHashSet = new LinkedHashSet<>();

LinkedHashSet.add("A");
LinkedHashSet.add("B");
LinkedHashSet.add("C");
LinkedHashSet.add("D");
LinkedHashSet.add("E");

String[] values = new String[LinkedHashSet.size()];

LinkedHashSet.toArray(values);

System.out.println(Arrays.toString(values));

程序输出:

[A, B, C, D, E]

5.3 将LinkedHashSet转换为ArrayList示例

使用Java 8 流 APILinkedHashSet转换为arraylist的 Java 示例。

LinkedHashSet<String> LinkedHashSet = new LinkedHashSet<>();

LinkedHashSet.add("A");
LinkedHashSet.add("B");
LinkedHashSet.add("C");
LinkedHashSet.add("D");
LinkedHashSet.add("E");

List<String> valuesList = LinkedHashSet.stream().collect(Collectors.toList());

System.out.println(valuesList);

程序输出:

[A, B, C, D, E]

6. LinkedHashSet用例

LinkedHashSet非常类似于ArrayList(有序)和HashSet(唯一元素)。 此外,它还保证了元素的迭代顺序(按插入元素的顺序)。

LinkedHashSet的实际用例可以存储流中的数据,其中流可能包含按所需顺序的重复记录,我们只对不同的记录感兴趣,但顺序完全相同。

另一个用例是在给定的句子中找到不同的单词,并且单词的顺序应该固定,因为它们出现在句子中。

7. LinkedHashSet性能

  • LinkedHashSet类为基本操作(添加,删除,包含和大小)提供O(1)恒定时间性能,假设哈希函数将元素正确分散在存储桶中。
  • 由于维护链表(除了一个迭代例外)会增加开销,因此性能可能会略低于HashSet

    LinkedHashSet上进行迭代需要的时间与集合的大小成正比,而不管其容量如何。 在HashSet上进行迭代可能会更昂贵,需要的时间与其容量成正比。 因此,LinkedHashSet可以在迭代时提供比HashSet更好的性能。

8. 总结

从上面的讨论中可以明显看出,LinkedHashSet在我们要以某种固定顺序处理重复记录的情况下是非常有用的集合类。 它为基本操作提供了可预测的性能。

如果不需要元素的迭代顺序,则建议改用较轻量的HashSetHashMap

在评论中向我发送与 Java 中的 LinkedHashSet有关的问题。

学习愉快!

参考:

LinkedHashSet Java 文档