这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
Set 是 Java 中常用集合之一,其重点实现类包括 HashSet、LinkedHashSet 和 TreeSet。
HashSet
HashSet 通过 hash 表存储元素 ,其底层是 HashMap。HashSet 的数据就是 HashMap 的键,HashMap 的值为空对象。
- HashSet 的底层是什么?
由其构造方法可以发现,当我们创建一个 HashSet 对象时,其实就是创建了一个键为指定数据,值为空 Object 类型的 HashMap。
1 | java复制代码 // 用来存储 HashSet 数据的变量 |
- HashSet 的初始容量是多少,负载因子是多少?
因为 HashSet 的底层是 HashMap,所以其初始容量为 16,负载因子为 0.75。同样也可以根据其构造方法推测出该值。
1 | java复制代码 public HashSet(Collection<? extends E> c) { |
- HashSet 能保证保证元素的顺序吗?
HashSet 通过 hash 表存储元素,因此一般认为 HashSet 插入的元素是无序的。但是也可以通过指定构造方法(该方法的权限为 default)来保持插入数据的顺序,此时其底层为 LinkedHashMap。而这也就是为什么 LinkedHashSet 能维持元素有序的原因。
1 | java复制代码 HashSet(int initialCapacity, float loadFactor, boolean dummy) { |
LinkedHashSet
LinkedHashSet 的底层为 LinkedHashMap,其链表保证了元素的插入与遍历顺序,哈希表保证了元素的唯一性。LinkedHashSet 的初始容量同样为 16,负载因子为 0.75。
1 | csharp复制代码 public LinkedHashSet() { |
TreeSet
TreeSet 通过二叉树存储数据,其底层是 TreeMap。二叉树结构保证了元素的顺序,默认为自然排序,可以通过实现 Compareable 接口,并重写里面的compareTo() 方法来进行自定义排序。
1 | java复制代码 public TreeSet() { |
HashSet 与 LinkedHashSet 的区别
HashSet 不能保证元素的顺序,而 LinkedHashSet 可以保证元素的顺序。
TreeSet 与 LinkedHashSet 的区别
LinkedHashSet 保证的是元素的插入与遍历顺序一致,而 TreeSet 是插入时根据规则排好序,其有序性的意义是不同的。
总结
HashSet、LinkedHashSet 和 TreeSet 都是线程不安全的,在多线程环境中,可以使用Collections.synchronizedSet(new HashSet<>())
或者new CopyOnWriteArraySet<>()
。
本文转载自: 掘金