The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
The Set
implementations are grouped into general-purpose and special-purpose implementations.Set
实现分为通用和专用实现。
There are three general-purpose 有三种通用Set
implementations HashSet
, TreeSet
, and LinkedHashSet
. Set
实现#151; HashSet
、TreeSet
和LinkedHashSet
。Which of these three to use is generally straightforward. 使用这三个选项中的哪一个通常很简单。HashSet
is much faster than TreeSet
(constant-time versus log-time for most operations) but offers no ordering guarantees. HashSet
比TreeSet
快得多(对于大多数操作来说,是固定时间还是日志时间),但不提供排序保证。If you need to use the operations in the 如果需要使用SortedSet
interface, or if value-ordered iteration is required, use TreeSet
; otherwise, use HashSet
. SortedSet
接口中的操作,或者如果需要按值排序的迭代,请使用TreeSet
;否则,使用HashSet
。It's a fair bet that you'll end up using 可以肯定的是,你最终大部分时间都会使用HashSet
most of the time.HashSet
。
LinkedHashSet
is in some sense intermediate between 在某种意义上介于HashSet
and TreeSet
. HashSet
和TreeSet
之间。Implemented as a hash table with a linked list running through it, it provides insertion-ordered iteration (least recently inserted to most recently) and runs nearly as fast as 它作为一个哈希表实现,并在其中运行一个链表,它提供了按插入顺序的迭代(从最近插入到最近插入),运行速度几乎与HashSet
. HashSet
一样快。The LinkedHashSet
implementation spares its clients from the unspecified, generally chaotic ordering provided by HashSet
without incurring the increased cost associated with TreeSet
.LinkedHashSet
实现使其客户机免受HashSet
提供的未指明、通常混乱的排序,而不会增加与TreeSet
相关的成本。
One thing worth keeping in mind about 关于HashSet
is that iteration is linear in the sum of the number of entries and the number of buckets (the capacity). HashSet
,值得记住的一点是,迭代在条目数和桶数(容量)之和上是线性的。Thus, choosing an initial capacity that's too high can waste both space and time. 因此,选择过高的初始容量可能会浪费空间和时间。On the other hand, choosing an initial capacity that's too low wastes time by copying the data structure each time it's forced to increase its capacity. 另一方面,选择太低的初始容量会浪费时间,因为每次强制增加容量时都会复制数据结构。If you don't specify an initial capacity, the default is 16. 如果不指定初始容量,默认值为16。In the past, there was some advantage to choosing a prime number as the initial capacity. 在过去,选择素数作为初始容量有一些优势。This is no longer true. 这不再是事实。Internally, the capacity is always rounded up to a power of two. 在内部,容量总是四舍五入到二的幂。The initial capacity is specified by using the 初始容量由int
constructor. int
构造函数指定。The following line of code allocates a 下面的代码行分配一个初始容量为64的HashSet
whose initial capacity is 64.HashSet
。
Set<String> s = new HashSet<String>(64);
The HashSet
class has one other tuning parameter called the load factor. HashSet
类还有一个名为load factor的调优参数。If you care a lot about the space consumption of your 如果您非常关心HashSet
, read the HashSet
documentation for more information. HashSet
的空间消耗,请阅读HashSet
文档以了解更多信息。Otherwise, just accept the default; it's almost always the right thing to do.否则,就接受默认值;这几乎总是正确的做法。
If you accept the default load factor but want to specify an initial capacity, pick a number that's about twice the size to which you expect the set to grow. 如果您接受默认的负载系数,但希望指定初始容量,请选择一个大约是预期集增长到的大小的两倍的数字。If your guess is way off, you may waste a bit of space, time, or both, but it's unlikely to be a big problem.如果你的猜测有偏差,你可能会浪费一些空间、时间,或者两者都浪费,但这不太可能是个大问题。
LinkedHashSet
has the same tuning parameters as HashSet
, but iteration time is not affected by capacity. LinkedHashSet
与HashSet
具有相同的调优参数,但迭代时间不受容量的影响。TreeSet
has no tuning parameters.TreeSet
没有调整参数。
There are two special-purpose 有两种特殊用途的Set
implementations EnumSet
and CopyOnWriteArraySet
.Set
实现EnumSet
和CopyOnWriteArraySet
。
EnumSet
is a high-performance Set
implementation for enum types. EnumSet
是针对枚举类型的高性能Set
实现。All of the members of an enum set must be of the same enum type. 枚举集的所有成员必须是同一枚举类型。Internally, it is represented by a bit-vector, typically a single 在内部,它由一个位向量表示,通常是一个long
. long
。Enum sets support iteration over ranges of enum types. 枚举集支持枚举类型范围内的迭代。For example, given the enum declaration for the days of the week, you can iterate over the weekdays. 例如,给定一周中几天的枚举声明,您可以迭代工作日。The EnumSet
class provides a static factory that makes it easy.EnumSet
类提供了一个静态工厂,使其变得简单。
for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY)) System.out.println(d);
Enum sets also provide a rich, typesafe replacement for traditional bit flags.枚举集还为传统的位标志提供了丰富的、类型安全的替代品。
EnumSet.of(Style.BOLD, Style.ITALIC)
CopyOnWriteArraySet
is a Set
implementation backed up by a copy-on-write array. CopyOnWriteArraySet
是一个Set
实现,由写时拷贝阵列备份。All mutative operations, such as 所有的变异操作,如add
, set
, and remove
, are implemented by making a new copy of the array; no locking is ever required. add
、set
和remove
,都是通过创建数组的新副本来实现的;不需要锁。Even iteration may safely proceed concurrently with element insertion and deletion. 甚至迭代也可以安全地与元素插入和删除同时进行。Unlike most 与大多数Set
implementations, the add
, remove
, and contains
methods require time proportional to the size of the set. Set
实现不同,add
、remove
和contains
方法需要与Set
大小成比例的时间。This implementation is only appropriate for sets that are rarely modified but frequently iterated. 这种实现只适用于很少修改但经常迭代的集合。It is well suited to maintaining event-handler lists that must prevent duplicates.它非常适合维护必须防止重复的事件处理程序列表。