java 如何在java 8流上使用foreach循环进行迭代
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31702989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to iterate with foreach loop over java 8 stream
提问by Vadzim
Suppose we try to apply to java 8 stream a lambda that could throw checked exception:
假设我们尝试将一个可能抛出检查异常的 lambda 应用于 java 8 流:
Stream<String> stream = Stream.of("1", "2", "3");
Writer writer = new FileWriter("example.txt");
stream.forEach(s -> writer.append(s)); // Unhandled exception: java.io.IOException
This won't compile.
这不会编译。
One workaround is to nest checked exception in RuntimeException
but it complicates later exception handling and it's just ugly:
一种解决方法是将检查过的异常嵌套在其中,RuntimeException
但它会使以后的异常处理复杂化,而且很难看:
stream.forEach(s -> {
try {
writer.append(s);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
Alternative workaround could be to convert limitedfunctional forEach
to plain old foreachloopthat is more friendly to checked exceptions.
另一种解决方法可能是转换限制功能forEach
,以普通的旧的foreach循环是比较友好的检查的异常。
But naive approaches fail:
但是幼稚的方法失败了:
for (String s : stream) { // for-each not applicable to expression type 'java.util.stream.Stream<java.lang.String>'
writer.append(s);
}
for (String s : stream.iterator()) { // foreach not applicable to type 'java.util.Iterator<java.lang.String>'
writer.append(s);
}
Update
更新
A trick that answers this question was previosly posted at Why does Stream<T> not implement Iterable<T>?as side answerthat doesn't really answer that question itself. I think this is not enough to qualify this question as duplicate of that one because they ask different things.
之前在为什么 Stream<T> 不实现 Iterable<T> 上发布了一个可以回答这个问题的技巧?作为并没有真正回答这个问题本身的辅助答案。我认为这不足以使这个问题与那个问题重复,因为他们问的是不同的事情。
回答by Vadzim
By definitionforeach loop requires an Iterableto be passed in.
根据定义,foreach 循环需要传入一个Iterable。
It can be achieved with anonymous class:
可以通过匿名类来实现:
for (String s : new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return stream.iterator();
}
}) {
writer.append(s);
}
This can be simplified with lambdabecause Iterable
is a functional interface:
这可以用lambda简化,因为它Iterable
是一个功能接口:
for (String s : (Iterable<String>) () -> stream.iterator()) {
writer.append(s);
}
This can be converted to method reference:
这可以转换为方法参考:
for (String s : (Iterable<String>) stream::iterator) {
writer.append(s);
}
Explicit cast can be avoided with intermediate variable or method param:
使用中间变量或方法参数可以避免显式转换:
Iterable<String> iterable = stream::iterator;
for (String s : iterable) {
writer.append(s);
}
There is also StreamExlibrary in maven central that features iterable streams and other perks out of the box.
maven 中心还有一个StreamEx库,它具有可迭代的流和其他开箱即用的特性。
Here is some most popular questions and approaches that provide workarounds on checked exception handling within lambdas and streams:
以下是一些最流行的问题和方法,它们提供了有关 lambda 和流中已检查异常处理的变通方法:
Java 8 Lambda function that throws exception?
Java 8: Lambda-Streams, Filter by Method with Exception
Java 8:Lambda-Streams,按带有异常的方法过滤
如何从 Java 8 流内部抛出 CHECKED 异常?(不将其包装成未经检查的异常)
Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?
Java 8:lambda 表达式中的强制检查异常处理。为什么是强制性的,而不是可选的?
Kotlin;)
科特林;)
回答by Brett Okken
Stream does not implement Iterable, nor is it an array, so it is not eligible for use in an enhanced for loop. The reason it does not implement Iterable is because it is a single use data structure. Each time Iterable.iterator is called, a new Iterator should be returned which covers all of the elements. The iterator method on Stream just reflects the current state of the Stream. It is effectively a different view of the Stream.
Stream 没有实现 Iterable,也不是数组,因此不适合在增强的 for 循环中使用。它没有实现 Iterable 的原因是因为它是一次性使用的数据结构。每次调用 Iterable.iterator 时,都应该返回一个新的 Iterator,它涵盖了所有元素。Stream 上的迭代器方法仅反映 Stream 的当前状态。它实际上是 Stream 的不同视图。
You could make a class which implements Iterable by wrapping a stream for use in the enhanced for loop. But this is a questionable idea as you cannot truly implement Iterable (as described above).
您可以通过包装一个流以在增强的 for 循环中使用来创建一个实现 Iterable 的类。但这是一个有问题的想法,因为您无法真正实现 Iterable(如上所述)。
回答by Jeffrey
I wrote an extensionto the Stream API which allows for checked exceptions to be thrown.
我为 Stream API编写了一个扩展,它允许抛出已检查的异常。
Stream<String> stream = Stream.of("1", "2", "3");
Writer writer = new FileWriter("example.txt");
ThrowingStream.of(stream, IOException.class).forEach(writer::append);
回答by BullyWiiPlaza
You can also do it like this:
你也可以这样做:
Path inputPath = Paths.get("...");
Stream<Path> stream = Files.list(inputPath);
for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext(); )
{
Path path = iterator.next();
// ...
}