toList() 的实现明确返回一个 ArrayList,它确实保证了可变性:
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>(ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
但是 toList 的 JavaDoc 是这样写的:
/**
* Returns a {@code Collector} that accumulates the input elements into a
* new {@code List}. There are no guarantees on the type, mutability,
* serializability, or thread-safety of the {@code List} returned; if more
* control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
*
* @param <T> the type of the input elements
* @return a {@code Collector} which collects all the input elements into a
* {@code List}, in encounter order
*/
为什么不能保证可变性?我是否遗漏了返回的集合可能不可变的情况?当返回的集合需要可变性时,使用 Collectors.toList() 是否安全?
为什么不能保证可变性?
Collectors.toList
方法的设计者选择了这样。
toList()的实现显然返回一个ArrayList
这个事实只是一个实现细节。该细节仅适用于您研究的一种实现的一个版本。其他版本和其他实现可能会使用
ArrayList
以外的其他内容。
最重要的是文档所承诺的行为。引用 Javadoc:
返回一个
,将输入元素累积到一个新的Collector
中。不保证返回的List
的类型、可变性、可序列化性或线程安全性;如果需要对返回的列表进行更多控制,请使用List
。toCollection(Supplier)
对我来说似乎很清楚。我们已向您承诺,结果
List
可能是可变的,也可能是不可变的。
如果您想要一个可变/可修改的
List
,请从收集器生成的列表中创建一个新的。
List< Whatever > list = new ArrayList<>( collectorList ) ;
如果您想要一个不可变/不可修改的列表,我建议致电
List.copyOf
。
List< Whatever > list = List.copyOf( collectorList ) ;
一个问题:如果传递的列表已经不可修改,则该方法是无操作的。但传递的不可修改列表实际上可能是下面的可修改列表的视图。为了防止这种可能性,请创建一个新列表,然后传递到
List.copyOf
。
List< Whatever > list = List.copyOf( new ArrayList<>( collectorList ) ) ;