Java - 向不可变列表添加一个元素

Dan*_*nik 2 java collections list immutability

我需要一个不可变列表,我可以从中派生出第二个不可变列表,该列表保留前一个列表的所有元素以及 Java 中的一个附加元素(无需附加库)。

注意:这个问题类似于将单个元素添加到不可变集合的有效且优雅的方法是什么?但我需要一个清单,而且没有番石榴。

到目前为止我尝试过的:

var list = List.of(someArrayOfInitialElements);
var newList = Stream.concat(list.stream(), Stream.of(elementToAppend))
        .collect(CollectorsCollectors.toUnmodifiableList());
Run Code Online (Sandbox Code Playgroud)

这会起作用,但创建一个流并一个一个地复制元素对我来说似乎效率低下。鉴于List.of()将数据存储在基于字段或基于数组的数据结构中,您基本上可以批量复制内存。

有没有比使用流更有效的解决方案?我缺少的 Java 标准库中更好的数据结构?

Ell*_*sch 7

我会创建一个新的ArrayList附加元素,然后将其作为不可修改的列表返回。就像是,

private static <T> List<T> appendOne(List<T> al, T t) {
    List<T> bl = new ArrayList<>(al);
    bl.add(t);
    return Collections.unmodifiableList(bl);
}
Run Code Online (Sandbox Code Playgroud)

并测试它

public static void main(String[] args) {
    List<String> al = appendOne(new ArrayList<>(), "1");
    List<String> bl = appendOne(al, "2");
    System.out.println(bl); 
}
Run Code Online (Sandbox Code Playgroud)

我得到(不出所料):

[1, 2]

请参阅在 IdeOne.com 上运行的代码

  • 我想你错过了我们正在添加**一个元素**。为了实现潜在的并行性,您至少需要两个。 (2认同)

Bas*_*que 5

弗里施的答案是正确的,应该被接受。进一步说明\xe2\x80\xa6

\n

调用Collections.unmodifiableList会生成一个集合,该集合是原始可变列表的视图。因此,对原始列表的修改将“渗透”到不那么不可变的第二个列表。

\n

此问题不适用于该答案中显示的正确代码,因为新ArrayList对象故意超出范围。因此,无法访问该新列表进行修改。但在其他编码场景中,这个问题可能会引起关注。

\n

List.copyOf

\n

如果您想要一个独立且真正不可变的第二个列表,请List.copyOfJava 10 + 中使用。这将返回一个不可修改的列表

\n
return List.copyOf( bl ) ;\n
Run Code Online (Sandbox Code Playgroud)\n