从对象数组实例化可修改列表的非详细方式,即没有双重实例化

Non-verbose way of instantiating a modifiable List from an array of objects, i.e. without double instantiation

我了解到这是从数组中实例化可修改列表的最可行方法

List<A> aList = new ArrayList<>(Arrays.asList(anArray));

是否有另一种无需双重实例化即可从数组中实例化可修改列表的方法?我认为将数组转换为列表然后再次将该列表转换为数组列表太多余了。

TIA!

您可以使用流 API :

List<A> aList = Stream.of(anArray).collect(Collectors.toCollection(ArrayList::new));

Arrays.asList(…) 在数组周围创建一个 wrapper。它不复制任何东西。事实上,列表支持通过所有不改变列表大小的方法来修改数组。

例如

String[] array = { "foo", "bar", "baz" };

List<String> aList = Arrays.asList(array);
aList.set(2, "blah");
aList.sort(Comparator.naturalOrder());
aList.replaceAll(String::toUpperCase);

System.out.println(Arrays.toString(array));
[BAR, BLAH, FOO]

因此,如果您不需要可调整大小的列表并且可以修改原始数组,那么只使用此列表而不将其复制到新的 ArrayList 可能是您的解决方案。


根据 Java 版本,ArrayList 的构造函数将只调用传入列表上的 toArray() 并将结果用作其自己的内部数组。对于这些版本,构造 new ArrayList<>(Arrays.asList(anArray)) 已经完成了从数组内容创建 ArrayList 所需的最少工作。

但在某些版本中,ArrayList 的构造函数会制作数组的防御性副本。如果你真的想确保在所有版本中都不会进行额外的数组复制操作,你可以使用

List<String> aList = new ArrayList<>(anArray.length);
Collections.addAll(aList, anArray);

但实际性能取决于复杂的周围条件,例如JIT 或缓存等可能会产生不直观的影响。结果可能是,即使在制作附加防御副本的版本中,new ArrayList<>(Arrays.asList(anArray)) 也会比任何替代方案都快。

底线是,使用简单惯用的 new ArrayList<>(Arrays.asList(anArray)) 方法,只有在遇到实际性能问题时才考虑替代方案。