Включено takeWhile () для потоков - PullRequest
1 голос
/ 01 апреля 2019

Я хочу знать, есть ли способ добавить последний элемент потока, который был протестирован с условием метода takeWhile (). Я считаю, что хочу добиться чего-то похожего на метод takeUntil () в RxJava.

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

Я искал по всему Stackoverflow практически безуспешно. Если вы думаете, что есть темы, которые могут решить мои проблемы, я бы, конечно, хотел бы увидеть это.

Если вы посмотрите на следующий код peek (), вы увидите, что число 5 проверяется на соответствие условию takeWhile (), но оно никогда не прибывает в forEach ():

IntStream.of(1, 3, 2, 5, 4, 6)
        .peek(foo -> System.out.println("Peek: " + foo))
        .takeWhile(n -> n < 5)
        .forEach(bar -> System.out.println("forEach: " + bar));

Ожидаемый результат - последний элемент, проверенный по условию takeWhile, попадет в forEach's System.out :: println. В этом случае это 5.

Спасибо всем!

Ответы [ 2 ]

4 голосов
/ 01 апреля 2019

Нет удобного способа сделать это с помощью обычного потокового API.Это возможно безобразным образом (вам нужно адаптировать эту реализацию, это просто обычный takeWhile "backported" для Java 8).

Этот парень написал библиотеку расширений потоков, которая имеет takeWhileInclusive.

Пример использования:

IntStreamEx.of(1, 3, 2, 5, 4, 6)
    .peek(foo -> System.out.println("Peek: " + foo))
    .takeWhileInclusive(n -> n < 5)
    .forEach(bar -> System.out.println("forEach: " + bar));
0 голосов
/ 06 июня 2019

Я добавляю ужасный подход, который может быть излишним для вашего (или любого) варианта использования, но просто для удовольствия.

public static void main(String[] args) {
    List<Integer> source = List.of(1, 3, 2, 5, 4, 6);
    Iterator<Integer> iterator = source.iterator();
    AtomicBoolean proceed = new AtomicBoolean(true);

    Stream
        .generate(() -> {
            if (!proceed.get() || !iterator.hasNext()) {
                return null;
            }
            int value = iterator.next();
            System.out.println("generate: " + value);
            proceed.set(value < 5);
            return value;
        })
        .takeWhile(Objects::nonNull)
        .forEach(bar -> System.out.println("forEach: " + bar));

}

Вывод будет:

generate: 1
forEach: 1
generate: 3
forEach: 3
generate: 2
forEach: 2
generate: 5
forEach: 5

Возможнохудшее в этом подходе состоит в том, что он дает generate() ответственность (проверяя, есть ли еще), что он не принадлежит ему.

...