如何将流收集到CopyOnWriteArrayList中

时间:2016-09-21 08:01:58

标签: intellij-idea java-8 java-stream collectors

我得到"不兼容的类型,必需:CopyOnWriteArrayList,found:Object"以下内容。我使用的是IntelliJ 2016.1.1。

CopyOnWriteArrayList<Foo> l = fields.stream()
                                    .distinct()
                                    .collect(toCollection(CopyOnWriteArrayList::new));

2 个答案:

答案 0 :(得分:2)

问题是fields的类型不合适,很可能是原始类型,它会将Stream链的泛型调用转换为未经检查的操作,返回其擦除类型,终端Object电话的collect

使用正确的类型,这没有问题,即

List<String> fields=Arrays.asList("foo", "bar", "baz", "foo");
CopyOnWriteArrayList<String> l =
    fields.stream()
          .distinct()
          .collect(Collectors.toCollection(CopyOnWriteArrayList::new));

的工作原理。但请注意,以这种方式构建CopyOnWriteArrayList相当昂贵,因为“写入时复制”这个名称已经表明了这一点。在每次插入时复制整个内容会导致二次时间复杂度。

解决方案是在转换为所需目标类型之前收集到更适合增量构建的临时集合。复制步骤可能看起来像开销,但与直接收集到CopyOnWriteArrayList二次复杂性相比,它是线性开销。

CopyOnWriteArrayList<String> l =
    fields.stream()
          .distinct()
          .collect(Collectors.collectingAndThen(
                              Collectors.toList(), CopyOnWriteArrayList::new));

请注意,在此特定情况下,distinct隐式在后台构建Set,因此我们可以通过显式构建Set来代替临时{{1}来提高性能并删除List步骤:

distinct

得出的结论是,对于这个特定的用例,我们可以更简单,更有效:

CopyOnWriteArrayList<String> l =
    fields.stream()
          .collect(Collectors.collectingAndThen(
                              Collectors.toCollection(LinkedHashSet::new),
                              CopyOnWriteArrayList::new));

答案 1 :(得分:1)

它的接缝就像你的字段对象不是Foo类型,否则它应该可以找到下面的工作代码。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

public class Foo {


    private String name;

    Foo(String name){

        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Foo [name=" + name + "]";
    }

    public static void main(String[] args) {
        List<Foo> fields = new ArrayList<>();
        fields.add(new Foo("aa"));
        fields.add(new Foo("bb"));
        CopyOnWriteArrayList<Foo> l = fields.stream().distinct().collect(Collectors.toCollection(CopyOnWriteArrayList::new));

        System.out.println("l"+l);
    }


}

PS:如果你的字段不是通用的,那么这也会给出错误