适用于流的包容性takeWhile()

时间:2019-04-01 10:38:13

标签: java java-stream java-9

我想知道是否有一种方法可以添加对方法takeWhile()的条件进行测试的流的最后一个元素。我相信我想实现与RxJava的takeUntil()方法类似的功能。

我猜没有直接的方法可以做到这一点(如果我弄错了,请纠正我),但是我想知道是否有合适的解决方法可以实现我现在所知道的。

我搜索了整个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的System.out :: println。在这种情况下为5。

谢谢大家!

2 个答案:

答案 0 :(得分:4)

没有使用常规流API来执行此操作的便捷方法。在an ugly way中是可能的(您需要调整此实现,对于Java 8来说,这只是普通的takeWhile“反向移植”)。

This guy已编写了具有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));

答案 1 :(得分:0)

我添加了一种可怕的方法,可能对您(或任何)用例来说是过大的,但是只是为了好玩。

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()承担责任(检查是否还有更多责任),该责任不属于它。