我想根据过滤器收集物品。但是,如果找不到匹配项,则不应初始化结果列表。我希望使用null而不是空列表。
flow
问题:大多数情况下,我会不找到匹配项,从而导致集合为空。这意味着在大多数情况下,即使我不需要该列表,它也会被实例化。
答案 0 :(得分:5)
Collecto.toList()
使用List
分配ArrayList::new
,这是一个非常便宜的操作,因为ArrayList
直到元素才实际分配支持数组被插入。构造函数所做的全部工作就是将内部Object[]
字段初始化为静态创建的空数组的值。仅当插入第一个元素时,实际的后备数组才会初始化为其“初始大小”。
那为什么要避免这种结构呢?听起来像是过早的优化。
如果您非常担心GC压力,那就不要使用Streams。流和收集器本身创建起来可能比列表要“昂贵得多”。
答案 1 :(得分:0)
我只想到一种情况,其中Collectors.toList()
之外的其他东西计算起来会很昂贵,否则请使用:
... collect(Collectors.collectingAndThen(list -> {
list.isEmpty() ? null: list;
}))
但是请记住,使用List
的人很可能会在缺少元素的情况下期望为空,而不是null。
创建一个空的ArrayList
相当便宜,懒惰只会使情况变得更糟。
否则,这是一个变体,如果您真的想要:
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;
}