我正在为初学者编写一个库,因此我试图尽可能地保持API的简洁性。
我的库需要做的事情之一是对大量的int或long类型的集合执行一些复杂的计算。有许多场景和业务对象需要用户从中计算这些值,因此我认为最好的方式是使用流来允许用户将业务对象映射到IntStream
或LongStream
,然后在收集器内部计算这些计算结果。
但是,IntStream和LongStream只有三个参数的collect方法:
collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)
而且它没有像Stream<T>
那样简单的collect(Collector)
方法。
因此,无法执行以下操作:
Collection<T> businessObjs = ...
MyResult result = businessObjs.stream()
.mapToInt( ... )
.collect( new MyComplexComputation(...));
我需要提供类似这样的供应商、蓄电池和组合器:
MyResult result = businessObjs.stream()
.mapToInt( ... )
.collect(
()-> new MyComplexComputationBuilder(...),
(builder, v)-> builder.add(v),
(a,b)-> a.merge(b))
.build(); //prev collect returns Builder object
这对我那些新手用户来说太过复杂了,而且很容易出错。
我的解决方法是创建静态方法,接受IntStream
或LongStream
作为输入,并为您隐藏集合器的创建和执行。
public static MyResult compute(IntStream stream, ...){
return .collect(
()-> new MyComplexComputationBuilder(...),
(builder, v)-> builder.add(v),
(a,b)-> a.merge(b))
.build();
}
但这不遵循使用流的常规约定:
IntStream tmpStream = businessObjs.stream()
.mapToInt( ... );
MyResult result = MyUtil.compute(tmpStream, ...);
因为你必须保存一个临时变量并将其传递给静态方法,或者在静态调用中创建流,这可能会与我的计算中的其他参数混淆。是否有更简洁的方法,在仍然使用IntStream或LongStream的情况下实现这一点?
Stream<Integer>
。你可以通过mapToObj(Function.identity())
从IntStream
中获取它。 - Dmitry GinzburgIntStream
一样编写基于int的接口,然后查看它是否会生成任何垃圾。 - the8472IntStream#boxed()
提供了相同的功能。 - the8472