猿问

如何在 java 8 流 api 中延迟初始化 Collectors.toList()?

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


List<String> match = list

            .stream()

            .filter(item -> item.getProperty == "match")

            .collect(Collectors.toList());


if (match != null && !match.isEmpty()) {

    //handle seldom match

}

问题:大多数时候我不会有匹配项,导致集合为空。这意味着即使我不需要它,大部分时间列表也会被实例化。


慕的地6264312
浏览 145回答 2
2回答

慕婉清6462132

Collecto.toList()分配ListusingArrayList::new这是一个非常便宜的操作,因为ArrayList在插入元素之前实际上不会分配支持数组。构造函数所做的就是将内部Object[]字段初始化为静态创建的空数组的值。只有在插入第一个元素时,实际的后备数组才被初始化为其“初始大小”。那么为什么要经历避免这种结构的痛苦呢?这听起来像是过早的优化。如果您非常担心 GC 压力,请不要使用 Streams。流和收集器本身的创建可能比列表要“昂贵”得多。

慕容3067478

我只考虑一种情况,除了Collectors.toList()计算成本高昂之外,否则使用:... collect(Collectors.collectingAndThen(list -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list.isEmpty() ? null: list;&nbsp; &nbsp;}))但请记住,List如果缺少元素,使用它的人很可能会期望一个空的,而不是空的。创造一个空ArrayList的非常便宜,在这里懒惰只会让事情变得更糟。否则,如果您真的想要,这里有一个变体可以推迟到 null :&nbsp;private static <T> List<T> list(Stream<T> stream) {&nbsp; &nbsp; Spliterator<T> sp = stream.spliterator();&nbsp; &nbsp; if (sp.getExactSizeIfKnown() == 0) {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Exact zero known");&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }&nbsp; &nbsp; T[] first = (T[]) new Object[1];&nbsp; &nbsp; boolean b = sp.tryAdvance(x -> first[0] = x);&nbsp; &nbsp; if (b) {&nbsp; &nbsp; &nbsp; &nbsp; List<T> list = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; list.add(first[0]);&nbsp; &nbsp; &nbsp; &nbsp; sp.forEachRemaining(list::add);&nbsp; &nbsp; &nbsp; &nbsp; return list;&nbsp; &nbsp; }&nbsp; &nbsp; return null;}
随时随地看视频慕课网APP

相关分类

Java
我要回答