当前位置: 首页 > 知识库问答 >
问题:

拾取列表中的元素,直到满足Java8Lambdas的条件

诸葛皓
2023-03-14

我试图改变我的想法,以功能的方式思考,最近面临着这样一种情况,我需要从列表中提取元素,直到满足一个条件,我找不到一个简单自然的方法来实现这一点。显然我还在学习。

假设我有这个清单:

List<String> tokens = Arrays.asList("pick me", "Pick me", "pick Me",
    "PICK ME", "pick me and STOP", "pick me", "pick me and Stop", "pick me");

// In a non lambdas was you would do it like below
List<String> myTokens = new ArrayList<>();
for (String token : tokens) {
    myTokens.add(token);
    if (token.toUpperCase().endsWith("STOP")) {
        break;
    }
}

提前感谢您的投入

注意:在发布这篇文章之前,我读了用谓词限制流,但是我不知道如何调整这个答案来解决我的问题。任何帮助将不胜感激。

共有3个答案

谯嘉胜
2023-03-14

使用严格Java8 API:

public static <R> Stream<? extends R> takeUntil(Iterator<R> iterator, Predicate<? super R> stopFilter) {
    final boolean isParallelStream = false;
    
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<R>() {
        private R next = null;
        private boolean conditionSatisfied = false;
        private boolean hasTaken = true;
        
        @Override
        public boolean hasNext() {
            if (conditionSatisfied || !iterator.hasNext()) {
                return false;
            }

            if (hasTaken) {
                next = iterator.next();
                conditionSatisfied = stopFilter.test(next);
                hasTaken = false;
            }
            return !conditionSatisfied;
        }

        @Override
        public R next() {
            if (!hasNext()) {
                throw new NoSuchElementException("There are no more items to consume");
            }
            hasTaken = true;
            return next;
        }
    }, 0), isParallelStream);
}

然后可以通过以下方式对其进行专门化:

public static <R> Stream<? extends R> takeUntil(Stream<R> stream, Predicate<? super R> stopFilter) {
    return takeUntil(stream.iterator(), stopFilter);
}
public static <R> Stream<? extends R> takeUntil(Collection<R> col, Predicate<? super R> stopFilter) {
    return takeUntil(col.iterator(), stopFilter);
}
锺星腾
2023-03-14

在JDK9中,将有一个名为takeWhile的新Stream操作,它做的事情与您需要的类似。我将此操作向后移植到我的StreamEx库中,因此您甚至可以在Java-8中使用它:

List<String> list = StreamEx.of(tokens)
                            .takeWhile(t -> !t.toUpperCase().endsWith("STOP"))
                            .toList();

不幸的是,它不接受“STOP”元素本身,因此需要第二次手动添加它:

list.add(StreamEx.of(tokens).findFirst(t -> t.toUpperCase().endsWith("STOP")).get());

请注意,两个teking同时findFirst都是短路操作(如果不必要,它们不会处理整个输入流),因此您可以将它们用于非常长甚至无限的流。

但是,使用StreamEx,您可以使用groupRuns的技巧一次性解决此问题。groupRuns方法根据提供的谓词将相邻的流元素分组到列表,该谓词告诉是否应将两个给定的相邻元素分组。我们可以认为,该组以包含<代码>“停止”< /代码>的元素结束。那么我们只需要看第一组:

List<String> list = StreamEx.of(tokens)
                            .groupRuns((a, b) -> !a.toUpperCase().endsWith("STOP"))
                            .findFirst().get();

当第一组完成时,这个解决方案也不会做额外的工作。

尉迟卓
2023-03-14

如果确实必须使用Streams API,请保持简单并使用索引流:

int lastIdx = IntStream.range(0, tokens.size())
        .filter(i -> tokens.get(i).toUpperCase().endsWith("STOP"))
        .findFirst()
        .orElse(-1);

List<String> myTokens = tokens.subList(0, lastIdx + 1);

或者,如果您想要不受原始列表支持的独立副本,则从子列表中创建一个新的列表。

 类似资料:
  • 问题内容: 我试图改变我的思维,以考虑功能性方法,最近遇到了一种情况,我需要从列表中选取元素,直到满足条件为止,而我找不到实现这一目标的简便方法。显然我还在学习。 说我有这个清单: 预先感谢您的输入 注意:在发布此内容之前,我阅读了通过谓词限制流,但是我看不到如何使该答案适应我的问题。任何帮助,将不胜感激谢谢。 问题答案: 一个选项使用需要两个函数的收集器,一个函数将字符串添加到列表,另一个函数合

  • 本文向大家介绍Python 找到列表中满足某些条件的元素方法,包括了Python 找到列表中满足某些条件的元素方法的使用技巧和注意事项,需要的朋友参考一下 如下所示: 以上这篇Python 找到列表中满足某些条件的元素方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。

  • 本文向大家介绍Python实现删除列表中满足一定条件的元素示例,包括了Python实现删除列表中满足一定条件的元素示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python实现删除列表中满足一定条件的元素。分享给大家供大家参考,具体如下: 从列表中删除满足一定条件的元素。 如:删除一个列表中长度为0的元素,或者删除列表中同时是2和3的倍数的元素。 做过高级语言编程的人想当然的会认为“

  • 假设我有这个HTML: 现在我要访问 ,它与标记在同一个tr中,带有href“Amazon”。最好的方法是什么?我需要一个for循环覆盖所有的div吗?还是我可以使用@findby注释?我是否需要多个@findby或@findall来获取列表中的所有div以便为Amazon检查这些div?

  • 所以我必须在eclipse中为我的类创建一个java项目。分配是创建一个程序,允许用户在程序中输入整数,直到输入某个整数(42)。输入整数(42)后,程序将为1。平均输入的所有数字。2、显示输入的最小值和最大值。3、输入的数字总数。这些必须在不计算(42)的情况下进行计算。这就是我目前所拥有的。我可以从用户那里获得输入,一旦他们输入42,程序就会停止并显示总数,但包括42。我不知道如何为输入添加一

  • 问题内容: 我想从这些数据结构中按值删除满足某些条件的元素 从上一个问题中,我找到了使用的简洁答案,但是似乎需要精确匹配。 在这里,我想从表或映射中删除其值小于特定阈值的元素。您编写代码的方式是什么? 我只检查了两个答案,这些是关于map的答案,表情况如何?我的解决方案如下。 问题答案: Iterator iterator = hmap.values().iterator(); while (it