Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java8流api中惰性初始化collector.toList()?_Java_Java 8_Java Stream - Fatal编程技术网

如何在Java8流api中惰性初始化collector.toList()?

如何在Java8流api中惰性初始化collector.toList()?,java,java-8,java-stream,Java,Java 8,Java Stream,我想根据过滤器收集项目。但如果没有找到匹配项,则不应初始化结果列表。我更喜欢空列表而不是空列表 List<String> match = list .stream() .filter(item -> item.getProperty == "match") .collect(Collectors.toList()); if (match != null && !match.isEmpty(

我想根据过滤器收集项目。但如果没有找到匹配项,则不应初始化结果列表。我更喜欢空列表而不是空列表

List<String> match = list
            .stream()
            .filter(item -> item.getProperty == "match")
            .collect(Collectors.toList());

if (match != null && !match.isEmpty()) {
    //handle seldom match
}
List match=List
.stream()
.filter(项目->项目.getProperty==“匹配”)
.collect(Collectors.toList());
if(match!=null&&!match.isEmpty()){
//句柄很少匹配
}
问题:大多数时候我都没有匹配项,导致集合为空。这意味着即使我不需要它,大多数时候列表都是实例化的。

Collecto.toList()
使用
ArrayList::new
分配一个
list
,这是一个非常便宜的操作,因为
ArrayList
实际上在插入元素之前不会分配支持数组。构造函数只需将内部
对象[]
字段初始化为静态创建的空数组的值。只有在插入第一个元素时,才将实际备份数组初始化为其“初始大小”

那么,为什么要经历避免这种建设的痛苦呢?这听起来像是过早的优化


如果您非常担心GC压力,就不要使用流。流和收集器本身创建的成本可能比列表要高出很多。

我只考虑一个情况,即除
Collector.toList()
之外的其他东西计算成本较高,否则使用:

... collect(Collectors.collectingAndThen(list -> {
          list.isEmpty() ? null: list;
   }))
但请记住,如果缺少元素,使用该
列表的人很可能会期望一个空列表,而不是空列表

创建一个空的
ArrayList
非常便宜,在这里懒惰只会让事情变得更糟

否则,如果您真的想要,这里有一个变量可以推迟到null:

 private static <T> List<T> list(Stream<T> stream) {
    Spliterator<T> sp = stream.spliterator();
    if (sp.getExactSizeIfKnown() == 0) {
        System.out.println("Exact zero known");
        return null;
    }

    T[] first = (T[]) new Object[1];
    boolean b = sp.tryAdvance(x -> first[0] = x);
    if (b) {
        List<T> list = new ArrayList<>();
        list.add(first[0]);
        sp.forEachRemaining(list::add);
        return list;
    }

    return null;
}
私有静态列表(流){
Spliterator sp=stream.Spliterator();
如果(sp.getExactSizeIfKnown()==0){
System.out.println(“精确零已知”);
返回null;
}
T[]first=(T[])新对象[1];
布尔b=sp.tryAdvance(x->first[0]=x);
如果(b){
列表=新的ArrayList();
列表。添加(第一个[0]);
sp.foreachleveling(列表::添加);
退货清单;
}
返回null;
}

是否可能有多个匹配项,或者您是否只关心找到的第一个匹配项?也许您不需要收集到列表中。那么
String match=List.stream().filter(item->“match.equalsIgnoreCase(item.getProperty())).findFirst().orElse(null)如何我关心找到的所有匹配项。这就是为什么我要收集到一个列表,而不是使用
.anyMatch()
ArrayList::new
是否意味着构造函数
new ArrayList()
分配了10个初始容量?查看
ArrayList
@Nikolas的源代码的实际实现。构造函数中未分配10的容量。只有在添加第一个元素时才会分配后备数组。@Nikolas afaik,这是Java 8中引入的一种优化,在观察到空的
ArrayList
实例到处飞来飞去是很常见的之后。@Holger从OpenJDK的JDK6和JDK7源代码看,似乎你是对的。
estimateSize()
之所以这样命名是因为它是一个估计值,而不是一个精确已知的大小,因此当
estimateSize()==0
时,它可能仍然有元素。除此之外,构造一个单元素数组并不比构造一个空的
ArrayList
便宜,因此在不改进空的情况下,你会使非空的情况变得更昂贵…@Holger同意第一种观点,第二次我想我清楚地表明,无论如何,在
ArrayList
的情况下这样做可能没有意义。谢谢你的评论