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