基本介绍

LinkedHashSet位于java.util包,在JDK1.4引入,实现了Set接口,继承自HashSet,查看UML类图如下所示:
LinkedHashSet.png
相比于HashSet,主要在于构造方法不同导致的底层原理的差异。在其父类HashSet的public构造方法中,都是基于HashMap实现,默认修饰符的构造方法HashSet(int initialCapacity, float loadFactor, boolean dummy)基于LinkedHashMap实现,这也正是LinkedHashSet的底层实现。

构造方法

  1. // super调用了HashSet中的构造方法,指定了初始大小和加载因子大小
  2. public LinkedHashSet(int initialCapacity, float loadFactor) {
  3. super(initialCapacity, loadFactor, true);
  4. }
  5. // super调用了HashSet中的构造方法,指定了初始大小和默认加载因子大小
  6. public LinkedHashSet(int initialCapacity) {
  7. super(initialCapacity, .75f, true);
  8. }
  9. // 无参构造,super调用,默认指定了初始大小16和加载因子0.75
  10. public LinkedHashSet() {
  11. super(16, .75f, true);
  12. }
  13. // 传入一个集合的构造方法,初始化大小由c的大小决定,并调用addAll初始化元素
  14. public LinkedHashSet(Collection<? extends E> c) {
  15. super(Math.max(2*c.size(), 11), .75f, true);
  16. addAll(c);
  17. }

总结

  • HashSet的底层实现为HashMap,LinkedHashSet的底层实现为LinkedHashMap,因此两种集合的特性也跟随其对应的实现。
  • HashMap中不能记录K的添加顺序,因此HashSet中的元素也是无序的,LinkedHashMap实现可以记录元素的添加顺序,因此LinkedHashSet元素的顺序由添加顺序而定。
  • LinkedHashSet提供HashSet中的操作,并允许 null 元素。假设哈希函数在桶中正确地分散元素。由于维护链表的额外费用,性能可能略低于HashSet 。但有一个例外:对LinkedHashSet的迭代需要与集合大小成正比的时间,而不管其容量如何。 HashSet的迭代可能会更昂贵,需要与其容量成正比的时间。
  • LinkedHashSet有两个影响其性能的参数:初始容量和负载因子。它们的定义与HashSet完全相同,对于此类而言,选择过高初始容量性能损耗不如HashSet严重,因为此类的迭代时间不受容量的影响。
  • LinkedHashSet不是线程安全的,如果需要保证安全可以使用Collections.synchronizedSet方法包装该集合。