Я поток строк и нулям, какКак правильно уменьшить поток в другой поток
Stream<String> str1 = Stream.of("A","B","C",null,null,"D",null,"E","F",null,"G",null);
Я хочу, чтобы уменьшить его в другой поток, в котором любая последовательность не пустая строка сочетал, то есть как
Stream<String> str2 = Stream.of("ABC", "", "D", "EF","G")
Первый способ, который я нашел - создать коллектор, что во-первых, уменьшить полный входной поток для одного объекта со списком всех объединенных строк, а затем создать новый поток из него:
class Acc1 {
final private List<String> data = new ArrayList<>();
final private StringBuilder sb = new StringBuilder();
private void accept(final String s) {
if (s != null)
sb.append(s);
else {
data.add(sb.toString());
sb.setLength(0);
}
}
public static Collector<String,Acc1,Stream<String>> collector() {
return Collector.of(Acc1::new, Acc1::accept, (a,b)-> a, acc -> acc.data.stream());
}
}
...
Stream<String> str2 = str.collect(Acc1.collector());
Но в этом случае перед любым использованием, если str2, даже как str2.findFirst(), поток ввода будет полностью обработан. Это время и память трудоемкой операцией и на бесконечности потока от некоторого генератора он не будет работать на всех
Другой способ - создать внешний объект, который будет держать промежуточное состояние и использовать его в flatMap():
class Acc2 {
final private StringBuilder sb = new StringBuilder();
Stream<String> accept(final String s) {
if (s != null) {
sb.append(s);
return Stream.empty();
} else {
final String result = sb.toString();
sb.setLength(0);
return Stream.of(result);
}
}
}
...
Acc2 acc = new Acc2();
Stream<String> str2 = str1.flatMap(acc::accept);
В этот случай из str1 будет извлекаться только в элементах, которые действительно доступны через str2.
Но использование внешнего объекта, созданного за пределами обработки потока, выглядит уродливо для меня и, вероятно, может вызвать некоторые побочные эффекты, которые я не вижу сейчас. Также, если str2 будет использоваться позже с parallelStream(), это вызовет непредсказуемый результат.
Есть ли более правильная реализация потоковой редукции без этих недостатков?
Существует библиотека «StreamEx», в которой содержится метод grouptun (не помните точное имя). Используя его, вы можете конвертировать поток в поток заполненных и пустых списков. Следующий шаг очевиден. – talex
Вы начинаете с «Потока» или с помощью «Коллекции»? Это оставило бы возможность использования spliterator –
Это может вас заинтересовать: http://stackoverflow.com/questions/29095967/splitting-list-into-sublists-along-elements/29096777 –