正如
LinkedHashSet
的文档所述,它是
Set接口的哈希表和链表实现,带 可预测的迭代顺序。此实现不同于 HashSet 因为它维护一个双向链表,贯穿其所有 条目。
所以它本质上是一个
HashSet
具有由链表实现的 FIFO 键队列。考虑到 LinkedList
是 Deque
并且特别允许在开头插入,我想知道为什么 LinkedHashSet
除了 addFirst(E e)
接口中存在的方法之外没有 Set
方法。实现起来似乎并不难。
正如 Eliott Frisch 所说,答案在您引用的段落的下一句中:
… 这个链表定义了迭代排序,也就是顺序 其中元素被插入到集合中(insertion-order)。 …
addFirst
方法会破坏插入顺序,从而破坏LinkedHashSet
的设计思想。
如果我也可以添加一些猜测,其他可能的原因可能包括:
LinkedHashSet
实际上是作为 LinkedHasMap
实现的,其中不使用映射到的值。至少你也必须改变那个类(这反过来也会破坏its插入顺序,从而破坏它的设计理念)。也就是说,你问的问题是错误的。他们设计了一个具有他们认为需要的功能的类。他们继续使用哈希表和链表来实现它。您从实施开始并将其用作设计讨论的基础。虽然这偶尔会增加一些有用的东西,但通常这不是好的设计的方式。
虽然理论上我可以理解您的观点,即可能存在您想要具有 set 属性的双端队列(重复项被忽略/消除)的情况,但我很难想象
Deque
何时无法满足您的需求在这种情况下(Eliott Frisch 提到了未充分使用的ArrayDeque
)。在 contains
和 remove
的线性复杂性令人望而却步之前,您需要相当大量的数据和/或非常严格的性能要求。在那种情况下,您可能已经更好地自定义设计自己的数据结构。
addFirst
方法被JEP 431:Sequenced Collections功能添加到
LinkedHashSet
。这是为即将到来的 Java 21 版安排的。
public void addFirst(E e)
添加一个元素作为该集合的第一个元素(可选操作)。此操作正常完成后,给定元素将成为此集合的成员,并且它将是遇到顺序中的第一个元素。
如果这个集合已经包含元素,它会在必要时重新定位,以便它在遇到顺序中排在第一位。
在界面中addFirst
`SequencedCollection<E>
参数:
- 要添加的元素e
自:
21
SequencedCollection
、SequencedSet
(扩展SequencedCollection
)和SequencedMap
。现有的类和接口已经过改造以使用新接口:SortedSet
和LinkedHashSet
实现SequencedSet
,List
和Deque
实现SequencedCollection
,以及SortedMap
和LinkedHashMap
实现SequencedMap
。
addFirst
上的LinkedHashSet
方法在SequencedCollection
中定义。
JDK enhancement proposal并没有解释为什么
LinkedHashSet
之前没有addFirst
方法。但在它的动机部分,它解释了为什么现在添加它和其他与序列相关的方法。
Java 的 collections 框架 缺少一个集合类型来表示具有定义的遇到顺序的元素序列。它还缺乏适用于此类集合的统一操作集。这些差距一直是问题和投诉的反复来源。
[…]
这是一种不幸的情况。集合框架中的多个地方都存在定义了遇到顺序的集合的概念,但没有一个单一的类型来表示它。结果,对此类集合的某些操作不一致或丢失,并且以相反的顺序处理元素从不方便到不可能。我们应该填补这些空白。