为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕的地6264312 2021-06-17 18:08:13
我想根据过滤器收集项目。但如果未找到匹配项,则不应初始化结果列表。我更喜欢 null 而不是空列表。List<String> match = list            .stream()            .filter(item -> item.getProperty == "match")            .collect(Collectors.toList());if (match != null && !match.isEmpty()) {    //handle seldom match}问题:大多数时候我不会有匹配项,导致集合为空。这意味着即使我不需要它,大部分时间列表也会被实例化。
查看完整描述

2 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

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

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

如果您非常担心 GC 压力,请不要使用 Streams。流和收集器本身的创建可能比列表要“昂贵”得多。


查看完整回答
反对 回复 2021-06-30
?
慕容3067478

TA贡献1773条经验 获得超3个赞

我只考虑一种情况,除了Collectors.toList()计算成本高昂之外,否则使用:


... collect(Collectors.collectingAndThen(list -> {

          list.isEmpty() ? null: list;

   }))

但请记住,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;

}


查看完整回答
反对 回复 2021-06-30
  • 2 回答
  • 0 关注
  • 144 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信