Я пишу библиотеку для начинающих программистов, поэтому я стараюсь, чтобы API был как можно более чистым.Почему примитивный поток не собирает (Collector)?
Одна из вещей, которые должна выполнять моя библиотека, - это выполнить некоторые сложные вычисления в большой коллекции ints или longs. Существует множество сценариев и бизнес-объектов, которые мои пользователи должны вычислить из этих значений, поэтому я подумал, что лучший способ - использовать потоки, чтобы позволить пользователям сопоставлять бизнес-объекты с IntStream
или LongStream
, а затем вычислять вычисления внутри коллектора.
Однако IntStream и LongStream только параметр 3 собрать метод:
collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)
И не имеет collect(Collector)
метод проще, что Stream<T>
имеет.
Таким образом, вместо того, чтобы быть в состоянии сделать
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, ...);
Потому что вы должны либо сохранить переменную временную и передать, что статический метод, или создать поток внутри статического вызова, который может ввести в заблуждение, когда он смешивается с другими параметрами в м y вычисление.
Есть ли более чистый способ сделать это, продолжая работать с IntStream
или LongStream
?
К сожалению, мой совет будет использовать 'Stream'. Вы можете получить его из 'IntStream'' mapToObj (Function.identity()) '. –
@DmitryGinzburg В потоке потенциально будет много тысяч элементов, и вычисление будет довольно сложным, я не хочу, чтобы вас наказывали все бокс/unboxing – dkatzel
, компилятор может устранить бокс/распаковку, если он может встроить путь кода от конверсии к вашим потребителям. Просто напишите их с помощью интерфейсов * int *, как и с 'IntStream', и посмотрите, генерирует ли он какой-либо мусор или нет. – the8472