如何使用 for 遍历 Java 中的流? [复制]

Posted

技术标签:

【中文标题】如何使用 for 遍历 Java 中的流? [复制]【英文标题】:How do I iterate over a stream in Java using for? [duplicate] 【发布时间】:2015-09-11 16:30:17 【问题描述】:

我有这个代码:

List<String> strings = Arrays.asList("a", "b", "cc");
for (String s : strings) 
    if (s.length() == 2)
        System.out.println(s);

我想使用过滤器和 lambda 来编写它:

for (String s : strings.stream().filter(s->s.length() == 2)) 
    System.out.println(s);

我收到Can only iterate over an array or an instance of java.lang.Iterable

我试试:

for (String s : strings.stream().filter(s->s.length() == 2).iterator()) 
    System.out.println(s);

我得到同样的错误。这甚至可能吗?我真的不想做 stream.forEach() 并传递一个消费者。

编辑:对我来说重要的是不要复制元素。

【问题讨论】:

如果您使用Stream,为什么首先要迭代?注意:你的代码可以写成strings.stream().filter(s -&gt; s.length() == 2).forEach(System.out::println) 如果它有效就不要重构。为了使用流而使用流不是使用流的方式:p 您将不得不原谅我的 C#...在那里您不会三思而后行将 IEnumerable 上的 if (...) continue 更改为 .where(!...) 这个问题的答案在@TagirValeev 链接到的问题的answer 中给出。 @fge forEachOrdered 可能更合适... 【参考方案1】:

您需要一个可迭代对象才能使用 for-each 循环,例如集合或数组:

for (String s : strings.stream().filter(s->s.length() == 2).toArray(String[]::new)) 

或者,您可以完全摆脱 for 循环:

strings.stream().filter(s->s.length() == 2).forEach(System.out::println);

你提到你不想重构你的 for 循环,但你可以用另一种方法提取它的主体:

strings.stream().filter(s->s.length() == 2).forEach(this::process);

private void process(String s) 
  //body of the for loop

【讨论】:

toArray() 是否复制元素?我忘了在原始问题中提到这一点,但我真的不想复制。 @ytoledano 是的,它会创建一个新数组并将元素引用复制到数组中。 谢谢,我保持原样。 @assylias,在重构旧代码时,可能会有很多不同的事情阻止您使用 lambda,例如可变变量或检查异常。从 Java-8 的角度来看,这可以被认为是糟糕的设计,但它仍然是有效且应该支持的代码。一次重构所有内容可能会有问题。我个人看到很多for 循环可能受益于流API,但不能轻易转换为forEach/collect。另请注意,与 lambda 相比,for 循环更容易调试。 @TagirValeev 当然 - 在某些情况下 for 循环更容易且更具可读性。我只是说,如果不知道循环内部是什么,就很难说流是否合适。

以上是关于如何使用 for 遍历 Java 中的流? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何循环遍历 Java 中的枚举? [复制]

java使用foreach语句遍历二维数组如何实现?

JAVA中数组如何打印出来

如何正确遍历删除List中的元素(普通for循环增强for循环迭代器iteratorremoveIf+方法引用)

java 使用socket编程,读出7个字节的流,如何转化为日期格式?

当我们不知道数组的大小时,如何遍历整数数组? [复制]