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