Stream takeWhile для отсортированного потока в том же конвейере - PullRequest
4 голосов
/ 01 ноября 2019

Я пытаюсь отфильтровать отсортированный поток, используя takeWhile из java9, чтобы получить объекты из начала потока, которые имеют одинаковое значение для поля. Я не могу написать правильный предикат для этого. Это можно сделать, используя два шага, нарушая конвейер потока.

Stream.of(objA, objB, objC, objD, objE, objF, objG)
    .takeWhile(" get the value of objA´s field and take 
   as long as as other objects value for that field is the same as objA´s");

В два шага я мог бы сделать что-то вроде

int x = Stream.of(objA, objB, objC, objD, objE, objF, objG).findFirst().get().getSomeValue();

Stream.of(objA, objB, objC, objD, objE, objF, objG).takeWhile(e -> e.getSomeValue() == x);

Упрощенный пример может быть

Stream.of(5,5,5,5,13,14,5,5,2,5,5,6)
.takeWhile(get the first four '5'´s)

Можно ли это сделать без промежуточного шага, используя option.get?

1 Ответ

3 голосов
/ 01 ноября 2019

Обходной путь (немного неуклюжий) - использовать объект изменяемого держателя (потому что ссылка должна быть эффективно окончательная ), которая содержит либо null, либо первое значение. Мы будем использовать AtomicReference в этом примере.

AtomicReference<MyClass> holder = new AtomicReference<>();

sortedStream.takeWhile(e -> holder.get() == null || holder.get().equals(e))
.map(e -> { holder.set(e); return e; })
.collect(Collectors.toList());

Теперь это все еще содержит дополнительный шаг, но поскольку Stream может быть обработан только один раз, подход findFirst() не будет работать в любом случае,При этом также сохраняется настройка объекта-держателя, даже если он был установлен, но это всего лишь небольшая досада, а не проблема.

Как отметил Хольгер, лучшей и более обтекаемой версией будет

sortedStream.takeWhile(e -> holder.compareAndSet(null, e.getSomeValue()) || e.getSomeValue() == holder.get())
.collect(Collectors.toList());

где с первым элементом compareAndSet присваивает значение, возвращая true, а последующие элементы сравниваются со значением владельца.

Если вы используете этот подход, я рекомендую добавить комментарий, указывающий на этовопрос / ответ или, по крайней мере, каким-то образом попытайтесь объяснить, чего достигает этот код, так как он может быть неочевиден для людей, читающих код.

...