【问题标题】:Transforming a LinkedHashSet into a List将 LinkedHashSet 转换为列表
【发布时间】:2011-05-19 15:44:00
【问题描述】:
  • 假设列表 b 是一个 LinkedList。
  • 假设列表 a 也是一个 LinkedList。

问题:

  • 如何在恒定时间内附加这些列表?

有可能,因为 LinkedList 大概是一个双向链表(否则它无法实现 Deque 接口)。并且追加双向链表是一个 0(1) 操作。

addAll 方法不会在恒定时间内运行。

问题:

  • 如何在恒定时间内将 LinkedHashSet 转换为列表?

这也是可能的,因为LinkedHashSet“维护一个贯穿其所有条目的双向链表”。

【问题讨论】:

    标签: java algorithm list


    【解决方案1】:

    您的假设基于没有封装 - 即 LinkedHashSet 愿意将其内部 LinkedList 暴露给外界,而我怀疑它不是。

    同样加入两个链表 - 我不知道每个节点是否知道它在哪个链表中,但这肯定会破坏你的常量时间附加。即使他们不这样做,一旦您将一个列表的头部附加到另一个列表的尾部,您最终就会遇到问题 - 您有两个列表都引用相同的数据,这会产生一些奇怪的后果。

    换句话说,这两种操作在计算机科学意义上都是可行的,您可以构建自己的自己的实现来支持它们,但这并不意味着 Java API 将其内部暴露在一种启用这些操作的方法。

    【讨论】:

    • Java 还没有附加 LinkedList 的方法吗?这些方法当然应该使用 LinkedList 而不是 List,因为它们根本无法使用 ArrayList。将 LinkedHashSet 转换为 LinkedList 也是如此。实际上,这就是我的问题的重点。
    • @Klems:不,我不相信它 - 因为你有两个共享节点的 LinkedList 对象。同样,如果调用者随后修改了返回的列表,您如何建议从 LinkedHashSet 创建 LinkedList 而不会引入可能的损坏? (我想它可能会返回一个不可变的视图。)
    • 哦,我现在看到了问题。好吧,正如你所说,它可以返回一个只读列表。这有点像返回一个迭代器。但是,要追加 2 个列表,该方法可以清除 2 个初始列表并返回结果列表。但我明白你的意思。
    • @Klems:嗯,你已经可以返回一个迭代器了……集合本身是可迭代的。如果您只能从中读取,那么拥有 LinkedList 有什么好处?
    • @Klems:我认为我们必须同意不同...但是您可以使用该属性轻松构建自己的实现。
    【解决方案2】:

    您需要实现自己的类。 LinkedList 类不公开其内部节点结构,因此您不能只将其最后一个节点指向另一个 LinkedList 的第一个节点。

    LinkedHashSet 的答案与此类似:虽然它确实维护了这个双向链表,但您无法访问它。

    【讨论】:

    • 由于 LinkedHashSet 实现了抽象集合接口,您可以访问该列表。请参阅@Michael McGrady 的回答
    【解决方案3】:

    您无法访问它,但我怀疑 Collections 可以,因此您不应放弃希望这是解决问题的可行且快速的解决方案。

    我看得更远,你是对的。如果你有Set<Whatever> whatever = SOME CONSTRUCTOR,那么你可以编码List<Whatever> list = new LinkedList(whatever);,因为 LinkedList 有一个 Collections 构造函数,而 Set 有一个 Collections 接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-27
      • 2013-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-30
      相关资源
      最近更新 更多