Java - 向不可变列表添加一个元素
Java - Add one element to an immutable list
我需要一个不可变列表,我可以从中派生第二个不可变列表,保留前一个列表的所有元素以及 Java 中的一个附加元素(没有附加库)。
Note: This question is similar to What is an efficient and elegant way to add a single element to an immutable set? but I need a list and don't have Guava.
到目前为止我尝试过的:
var list = List.of(someArrayOfInitialElements);
var newList = Stream.concat(list.stream(), Stream.of(elementToAppend))
.collect(CollectorsCollectors.toUnmodifiableList());
这可行,但创建一个流并一个一个地复制元素对我来说似乎效率低下。鉴于 List.of()
将数据存储在基于字段或基于数组的数据结构中,您基本上可以批量复制内存。
有没有比使用流更有效的解决方案?我缺少 Java 标准库中更好的数据结构?
我会创建一个新的 ArrayList
附加元素,然后 return 作为不可修改的列表。像,
private static <T> List<T> appendOne(List<T> al, T t) {
List<T> bl = new ArrayList<>(al);
bl.add(t);
return Collections.unmodifiableList(bl);
}
并对其进行测试
public static void main(String[] args) {
List<String> al = appendOne(new ArrayList<>(), "1");
List<String> bl = appendOne(al, "2");
System.out.println(bl);
}
我得到(不出所料):
[1, 2]
是正确的,应该接受。进一步注意...
正在呼叫 Collections.unmodifiableList
produces a collection that is a view onto the original mutable list。因此,对原始列表的修改将“渗透”到并非如此不可变的第二个列表。
此问题不适用于该答案中显示的正确代码,因为新的 ArrayList
对象故意超出范围。因此,无法访问该新列表进行修改。但在其他编码场景中,这个问题可能是一个问题。
List.copyOf
如果你想要一个独立且真正不可变的第二个列表,请使用List.copyOf
in Java 10+. This returns an unmodifiable list。
return List.copyOf( bl ) ;
两个答案都很好,我会创建一个更通用的解决方案:
private static <T> List<T> append(final List<T> al, final T... ts) {
final List<T> bl = new ArrayList<>(al);
for (final T t : ts) {
bl.add(t);
}
return List.copyOf(bl);
}
它可以像以前的答案一样使用:
List<String> al = append(new ArrayList<>(), "1");
List<String> bl = append(al, "2");
System.out.println(bl);
但效率也稍微高一点:
List<String> bl = append(new ArrayList<>(), "1", "2");
System.out.println(bl);
我需要一个不可变列表,我可以从中派生第二个不可变列表,保留前一个列表的所有元素以及 Java 中的一个附加元素(没有附加库)。
Note: This question is similar to What is an efficient and elegant way to add a single element to an immutable set? but I need a list and don't have Guava.
到目前为止我尝试过的:
var list = List.of(someArrayOfInitialElements);
var newList = Stream.concat(list.stream(), Stream.of(elementToAppend))
.collect(CollectorsCollectors.toUnmodifiableList());
这可行,但创建一个流并一个一个地复制元素对我来说似乎效率低下。鉴于 List.of()
将数据存储在基于字段或基于数组的数据结构中,您基本上可以批量复制内存。
有没有比使用流更有效的解决方案?我缺少 Java 标准库中更好的数据结构?
我会创建一个新的 ArrayList
附加元素,然后 return 作为不可修改的列表。像,
private static <T> List<T> appendOne(List<T> al, T t) {
List<T> bl = new ArrayList<>(al);
bl.add(t);
return Collections.unmodifiableList(bl);
}
并对其进行测试
public static void main(String[] args) {
List<String> al = appendOne(new ArrayList<>(), "1");
List<String> bl = appendOne(al, "2");
System.out.println(bl);
}
我得到(不出所料):
[1, 2]
正在呼叫 Collections.unmodifiableList
produces a collection that is a view onto the original mutable list。因此,对原始列表的修改将“渗透”到并非如此不可变的第二个列表。
此问题不适用于该答案中显示的正确代码,因为新的 ArrayList
对象故意超出范围。因此,无法访问该新列表进行修改。但在其他编码场景中,这个问题可能是一个问题。
List.copyOf
如果你想要一个独立且真正不可变的第二个列表,请使用List.copyOf
in Java 10+. This returns an unmodifiable list。
return List.copyOf( bl ) ;
两个答案都很好,我会创建一个更通用的解决方案:
private static <T> List<T> append(final List<T> al, final T... ts) {
final List<T> bl = new ArrayList<>(al);
for (final T t : ts) {
bl.add(t);
}
return List.copyOf(bl);
}
它可以像以前的答案一样使用:
List<String> al = append(new ArrayList<>(), "1");
List<String> bl = append(al, "2");
System.out.println(bl);
但效率也稍微高一点:
List<String> bl = append(new ArrayList<>(), "1", "2");
System.out.println(bl);