为什么 Collectors.toList() 不能保证可变性

问题描述 投票:0回答:1

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() 是否安全?

java collections java-8 java-stream collectors
1个回答
0
投票

为什么不能保证可变性?

因为

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 ) ) ;
© www.soinside.com 2019 - 2024. All rights reserved.