# 设置实现 > 原文: [https://docs.oracle.com/javase/tutorial/collections/implementations/set.html](https://docs.oracle.com/javase/tutorial/collections/implementations/set.html) `Set`实现分为通用和专用实现。 ## 通用集实现 有三种通用 [`Set`](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) 实现 - [`HashSet`](https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html) , [`TreeSet`](https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html) 和 [`LinkedHashSet`](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashSet.html) 。使用这三种中的哪一种通常是直截了当的。 `HashSet`比`TreeSet`快得多(大多数操作的恒定时间与对数时间),但不提供订购保证。如果需要使用`SortedSet`接口中的操作,或者需要按值进行迭代,请使用`TreeSet`;否则,请使用`HashSet`。这是一个公平的赌注,你最终会在大部分时间内使用`HashSet`。 `LinkedHashSet`在某种意义上介于`HashSet`和`TreeSet`之间。实现为具有贯穿其的链表的哈希表,它提供 _ 插入顺序 _ 迭代(最近最少插入到最近)并且运行几乎与`HashSet`一样快。 `LinkedHashSet`实现使其客户免于`HashSet`提供的未指定的,通常是混乱的排序,而不会导致与`TreeSet`相关的增加的成本。 关于`HashSet`值得记住的一件事是,迭代在条目数和桶数(_ 容量 _)之和中是线性的。因此,选择太高的初始容量会浪费空间和时间。另一方面,选择一个太低的初始容量会在每次强制增加容量时复制数据结构,从而浪费时间。如果未指定初始容量,则默认值为 16.过去,选择素数作为初始容量有一些优势。这不再是真的。在内部,容量总是四舍五入到 2 的幂。使用`int`构造函数指定初始容量。以下代码行分配初始容量为 64 的`HashSet`。 ``` Set s = new HashSet(64); ``` `HashSet`类还有一个称为 _ 加载因子 _ 的调整参数。如果您非常关心`HashSet`的空间消耗,请阅读`HashSet`文档以获取更多信息。否则,只接受默认值;这几乎总是正确的事情。 如果您接受默认加载因子但想要指定初始容量,请选择一个大约是您希望该组增长的大小的两倍的数字。如果您的猜测偏远,您可能会浪费一些空间,时间或两者,但这不太可能是一个大问题。 `LinkedHashSet`具有与`HashSet`相同的调整参数,但迭代时间不受容量影响。 `TreeSet`没有调整参数。 ## 专用集实现 有两个专用`Set`实现 - [`EnumSet`](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html) 和 [`CopyOnWriteArraySet`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArraySet.html) 。 `EnumSet`是枚举类型的高性能`Set`实现。枚举集的所有成员必须具有相同的枚举类型。在内部,它由位向量表示,通常是单个`long`。枚举在枚举类型的范围上设置支持迭代。例如,给定星期几的枚举声明,您可以迭代工作日。 `EnumSet`类提供了一个简单的静态工厂。 ``` for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY)) System.out.println(d); ``` 枚举集还为传统的位标志提供了丰富的,类型安全的替代品。 ``` EnumSet.of(Style.BOLD, Style.ITALIC) ``` `CopyOnWriteArraySet`是由写时复制阵列备份的`Set`实现。所有的变异操作,例如`add`,`set`和`remove`,都是通过制作数组的新副本来实现的;不需要锁定。甚至迭代也可以安全地与元素插入和删除同时进行。与大多数`Set`实现不同,`add`,`remove`和`contains`方法需要与集合大小成比例的时间。这种实现仅适用于适用于很少修改但经常迭代的集合。它非常适合维护必须防止重复的事件处理器列表。