【问题标题】:Filter stream until Predicate [duplicate]过滤流直到谓词[重复]
【发布时间】:2015-10-06 09:51:59
【问题描述】:

我有一个 Java 8 对象流,我想在匹配给定谓词后忽略这些对象。

示例:我想将所有字符串保留到“BREAK”字符串(包括它)。

public List<String> values = Arrays.asList("some", "words", "before", "BREAK", "AFTER");

@Test
public void testStopAfter() {
    Stream<String> stream = values.stream();
    //how to filter stream to stop at the first BREAK
    //stream = stream.filter(s -> "BREAK".equals(s));
    final List<String> actual = stream.collect(Collectors.toList());

    final List<String> expected = Arrays.asList("some", "words", "before", "BREAK");
    assertEquals(expected, actual);
}

因为它失败了(预期: 但结果是:),如果我取消注释过滤器,我只得到“BREAK”

我正在考虑一个有状态的谓词(请参阅下面的答案),但如果有更好的解决方案,我正在徘徊?

【问题讨论】:

  • 子流或类似的东西?
  • 看起来您想要原始流中的子流。
  • @LuiggiMendoza 是的,一个子流就可以了
  • @LouisWasserman 感谢您提供答案的链接。我没有找到它(错误的搜索关键字)。这不是一个确切的答案,因为我需要在输出中保留 BREAK (第一个匹配谓词),但是可以调整您的代码。谢谢。
  • @Benoît,实际上重复的链接是错误的。我将其更新为询问您的确切问题的问题。

标签: java java-8 java-stream


【解决方案1】:

使用有状态的谓词,在给定的谓词匹配之前和之后的答案为真。

[...]
stream = stream.filter(makeUntil(s -> "BREAK".equals(s)));
[...]


public static <T> Predicate<T> makeUntil(final Predicate<T> predicate) {
    return new Predicate<T>() {

        private boolean hasMatched;

        @Override
        public boolean test(final T s) {
            if (hasMatched) {
                return false;
            }
            else {
                hasMatched = predicate.test(s);
                return true;
            }
        }

    };
}

【讨论】:

  • 小心。这假设 Stream 是连续的,但可能并非每次都如此。
  • @LuiggiMendoza 非常好。关于如何检查的任何想法?
  • 您可以通过调用Stream#sequential 来确保流是连续的,以防您收到流作为参数,否则您可以使用这种方法
  • Streams 中做有状态的事情通常是个坏主意。
猜你喜欢
  • 2020-10-07
  • 2012-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
相关资源
最近更新 更多