【问题标题】:Is there an eqivalent to break in Java 8+ streams? [duplicate]在 Java 8+ 流中是否有等效的中断? [复制]
【发布时间】:2020-01-07 13:25:16
【问题描述】:

我正在尝试根据条件过滤列表。是否有其他方法可以中断我可以用来停止过滤的 java 8 流?

举个例子:假设我有以下列表。

List<String> list = Arrays.asList("Foo","Food" ,"Fine","Far","Bar","Ford","Flower","Fire");

list.stream()
        .filter(str -> str.startsWith("F")) //break when str doesn't start with F
        .collect(Collectors.toList());

我想要所有以“F”开头的字符串,一旦找到不以“F”开头的字符串,我想停止过滤。如果没有流,我会执行以下操作:

List<String> result = new ArrayList<>();
for(String s : list){
    if(s.startsWith("F")){
        result.add(s);
    }
    else{
        break;
    }
}

如何在流中使用“break”?

【问题讨论】:

  • 你可以使用 Java 9+ 吗?如果是这样,请参阅Stream#takeWhile(Predicate)
  • @Slaw 我还不知道这个功能。我可能已经尝试了一个小时。非常感谢,takeWhile 正是我所需要的。

标签: java lambda java-8 java-stream break


【解决方案1】:

您可以在 Java9 中使用 takeWhile 运算符,这正是您所需要的。这是它的外观。

List<String> res = list.stream()
    .takeWhile(s -> s.startsWith("F"))
    .collect(Collectors.toList());

【讨论】:

  • 我还不知道这个功能。我可能已经尝试了一个小时。非常感谢,这正是我需要的。
【解决方案2】:

这是一个使用 Java 8 的选项:

AtomicBoolean keepAdding = new AtomicBoolean(true);
list.stream()
    .peek(s -> keepAdding.set(keepAdding.get() && s.startsWith("F")))
    .filter(s -> keepAdding.get());

还有另一种可能性,从 cmets 可以看出,上述方法并不受欢迎:

list.subList(0, list.indexOf(list.stream().filter(s -> !s.startsWith("F"))
    .findFirst()
    .orElse(list.get(list.size() - 1))));

【讨论】:

  • 但是,这不能保证按预期运行。
  • @daniu 怎么样?你能举一个不符合预期的输入示例吗?
  • 过滤器不应该是有状态的
  • This answer 暗示不确定性,同时将peek 用于规则迭代的操作。
  • 我必须召唤@Holger 这样做,我已经看到他多次与人(包括我)在这个话题上发生冲突。编辑:aaand 我一直被 Naman 忍着,并带有指向 Holger 帖子之一的链接:D
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 2011-09-28
  • 2018-07-07
  • 1970-01-01
  • 2012-05-24
  • 2011-07-05
  • 2014-07-12
  • 2012-12-01
相关资源
最近更新 更多