【问题标题】:Java collection optimized for add (insert) operations only仅针对添加(插入)操作优化的 Java 集合
【发布时间】:2026-01-26 11:20:05
【问题描述】:

我正在寻找 Java 集合。我仅有的两个期望是:

  1. 快速O(1)插入/添加操作。

  2. 迭代此集合的能力。

我不关心元素顺序。

  • LinkedList 不是最佳候选,因为有很多小分配(对于每个新节点)。
  • ArrayList 不是最佳候选者,因为当没有更多空间时,内部数组会调整大小。

您能否提出针对此类操作优化的其他 Java 集合?

换句话说,我正在寻找LinkedListArrayList 之间的混合体。像LinkedList 这样的东西,额外的内存分配是为下一个 N 元素预先分配的——而不是像 LinkedList 这样的每个新元素。

【问题讨论】:

  • 你需要重复这个集合吗?如果你不关心重复,你可以使用 HashSet。
  • @Lorelorelore:是的,我关心重复。
  • 您可以拥有一个 ArrayList 的 LinkedList 并使用 Stream.flatMap 对其进行迭代
  • 如果您在开始添加之前知道大致长度,那么 ArrayList 可能会很好,因为您可以使用 .ensureCapacity()。但是,如果你在中间插入,你仍然需要移位,如果你真的想要 O(1) 插入,你可以使用 HashMap 或 ManyValuesMap (基本上是 Map> (iirc guava 有好的实现)如果顺序很重要,你也可以选择二叉树,但插入不会像 map 方法那么快
  • @PeterLawrey:据我所知Stream.flatMap 会在这里完成这项工作,但是:* 对于这个问题来说,这看起来有点矫枉过正 :) * 我不知道这种解决方案的性能如何.需要执行一些性能测量来资产运行时性能。

标签: java list arraylist collections linked-list


【解决方案1】:

既然您非常关心内存分配,请不要使用ArrayListLinkedList,而是使用易于操作和存储大数据的简单数组。

用 ex 分配数组的大小。 1'000'000 个元素:

MyClass[] array = new MyClass[1000000];
  • 将对象分配给数组索引也会花费O(1)
  • 使用for-loop,迭代很简单。

如果您希望执行其他操作,请使用for-loop 迭代。主要缺点是:

  • 一经声明即固定大小。
  • 可以存储单一类型。

另外,考虑 Stream-API(值得一试,我不知道这里的性能):

Arrays.stream(array)...

【讨论】:

  • 没有。我无法预先分配这么大的内存。
  • 内存有多大?
  • 我希望块的大小可以通过构造函数参数进行配置。但我们也可以假设这是 10 或 100 :)
  • 如果我理解你的话,你可以MyClass[] array = new MyClass[constructorArgument]; int constructorArgument 将是输入的大小?
  • 是的,我能做到。但是这个集合必须能够增长。我不知道特定集合是否包含 10 或 10'000'000 个元素。
【解决方案2】:

在 LinkedList 中,您不会为列表分配新内存,只是对新元素进行引用。

LinkedList 像链一样工作,包含对链中上一个/下一个元素的引用。 如果没有先前的元素意味着,这是第一个元素。如果没有对下一个元素的引用,这意味着它是列表的最后一个元素。 因此,添加新元素只是在“链”的末尾创建参考。

它使分配新元素的速度非常快,但是如果你想到达,例如列表中的第 10 个元素,它需要遍历“链”-> 所以这意味着它将从第一个元素开始访问每个元素一到十号。 与 ArrayList 相比,这是最大的缺点,其中到达具有指定索引的元素具有 O(1) 性能。 (使用 list.get(index) 方法)

【讨论】:

    【解决方案3】:

    您是否考虑过为java.util.Queue 使用队列?

    插入的时间复杂度为 O(1),并且可以使用迭代器进行迭代。

    【讨论】:

    • 但我担心 Java Queues 实现与我在原始问题中描述的 ArrayList 缺点有相同的缺点。