【问题标题】:Fetch the most recent inserted element in LinkedHashSet efficiently [duplicate]有效地获取 LinkedHashSet 中最近插入的元素[重复]
【发布时间】:2013-07-25 09:01:15
【问题描述】:

根据LinkedHashSet的Javadoc,内部会使用双向链表来保持插入元素的插入顺序。

它维护一个双向链表,贯穿其所有条目。 这个链表定义了迭代顺序,也就是在 哪些元素被插入到集合中(插入顺序)

如果我想获取第一个插入的元素,我可以使用如下代码:

linkedHashSet.iterator().next()

这将为我提供 O(1) 中集合中的第一个插入元素。

我正在尝试解决一个问题,这需要我在 O(1) 中访问集合中最近插入的元素,并且假设不会有任何重复的元素插入集合中。例如,

linkedHashSet.add(2); // the most recent inserted element in the set is 2
linkedHashSet.add(3); // the most recent inserted element in the set is 3
linkedHashSet.add(5); // the most recent inserted element in the set is 5
linkedHashSet.remove(5); // the most recent inserted element in the set is 3 because 5 is removed and not in the set now

由于它是集合中的双向链表,最近的元素似乎应该是双向链表中的最后一个元素,如果有一些 API 可以在 O(1) 内访问它.

我的问题是:JDK 中有什么方法可以做到这一点,还是我需要创建自己的 ReversedIteratingLinkedHashSet 来做到这一点?

基本上,我尝试为所有操作找到具有 O(1) 时间复杂度的 Set 数据结构,包括:插入/删除/搜索/检查集合中最近插入的元素。内置的 LinkedHashSet 似乎很适合在内部进行非常小的修改,但我不确定这是否可以使用默认的 JDK 类 API 来完成。

注意: 我查看了 JDK 的源代码,知道 LinkedHashSet 在内部是用 LinkedHashMap 实现的,如果有任何解决方案可以使用 LinkedHashMap 来访问 O(1) 中最近插入的元素,它对我也很有用。

非常感谢。

【问题讨论】:

  • 请覆盖我的教程Internal life of LinkedHashMap 以更好地了解 LinkedHashSet,因为后者只是前者的包装
  • 我建议在这里使用 LinkedHashMap。因为在插入一个映射之后,你可以通过按键非常快速地得到它。反正 LinkedHashSet 就是 LinkedHashMap。

标签: java data-structures hashset doubly-linked-list linkedhashset


【解决方案1】:

不幸的是,似乎没有直接/干净的方式来访问 O(1) 中 LinkedHashSet(或 LinkedHashMap)中最近添加的元素。

一种简洁的方法是将集合转换为数组并访问最后一个元素,但这将是 O(n)。

一种肮脏的方式是使用反射来访问内部哈希映射、映射的头条目,最后是条目的前身 (before)。

【讨论】:

  • 感谢您让我知道这样做的“肮脏方式”,我最终编写了自己的 LinkedHashSet 变体。
  • @VolodymyrLevytskyi 除了你的举止(称某人是骗子),你还应该证明你的说法。迭代时,最近插入的元素排在最后,除非您有自己的实现反之亦然。
  • 对不起!事实上,最近添加的元素位于链表的头部,并且在迭代时是最后一个......
  • @VolodymyrLevytskyi 我查看了代码(在 JDK 6 中,但我怀疑有很多更改),但这似乎不是真的。 header 条目将始终为空条目,并且任何新条目都将添加到标题之前。但是,由于列表是双向链接的,因此除了引用为 header 的元素之外没有真正的“头”,而且这个引用似乎根本没有改变。
  • 变量“header”通过其“after”变量引用第一个插入的元素,并通过其“before”变量引用最近添加的元素。每当您迭代链表时,都会使用变量“header”,因为它的“after”变量引用了第一个插入的条目。变量“header”也有它的“before”变量,每当创建新条目时都会使用它。 header.before 引用最近插入的条目,以便将未来的条目链接到当前包含链表的条目。涵盖我的教程,它会变得清晰。我草率地弄错了迭代顺序。
猜你喜欢
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 2021-05-11
  • 2017-02-20
  • 1970-01-01
  • 1970-01-01
  • 2013-06-20
  • 1970-01-01
相关资源
最近更新 更多