如何在java 8流上使用foreach循环进行迭代 [英] How to iterate with foreach loop over java 8 stream

查看:29
本文介绍了如何在java 8流上使用foreach循环进行迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们尝试将一个可能抛出已检查异常的 lambda 应用于 java 8 流:

Suppose we try to apply to java 8 stream a lambda that could throw checked exception:

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

这不会编译.

一种解决方法是在 RuntimeException 中嵌套检查异常,但它使以后的异常处理复杂化,而且很难看:

One workaround is to nest checked exception in RuntimeException but it complicates later exception handling and it's just ugly:

stream.forEach(s -> {
    try {
        writer.append(s);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
});

替代解决方法可能是转换有限功能forEach普通的 foreach循环,对检查异常更友好.

Alternative workaround could be to convert limited functional forEach to plain old foreach loop that is more friendly to checked exceptions.

但是幼稚的方法失败了:

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);
}

更新

之前在为什么Stream<T>不实现 Iterable<T>? 作为 side answer 本身并没有真正回答这个问题.我认为这不足以将这个问题与那个问题重复,因为他们问的是不同的事情.

A trick that answers this question was previosly posted at Why does Stream<T> not implement Iterable<T>? as side answer that 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.

推荐答案

根据定义 foreach 循环需要一个 Iterable 被传入.

By definition foreach loop requires an Iterable to be passed in.

可以用匿名类来实现:

    for (String s : new Iterable<String>() {
        @Override
        public Iterator<String> iterator() {
            return stream.iterator();
        }
    }) {
        writer.append(s);
    }

这可以通过 lambda 简化,因为 Iterable 是一个函数式接口::>

This can be simplified with lambda because Iterable is a functional interface:

    for (String s : (Iterable<String>) () -> stream.iterator()) {
        writer.append(s);
    }

这可以转换为方法参考:

    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);
    }


maven 中心还有 StreamEx 库,具有可迭代的流和其他开箱即用的功能.


There is also StreamEx library in maven central that features iterable streams and other perks out of the box.

以下是一些最流行的问题和方法,它们提供了有关 lambdas 和流中检查异常处理的变通方法:

Here is some most popular questions and approaches that provide workarounds on checked exception handling within lambdas and streams:

Java 8 Lambda 函数抛出异常?

Java 8:Lambda-Streams,按方法过滤异常

如何从在 Java 8 流中?

Java 8:强制检查异常处理在 lambda 表达式中.为什么是强制性的,而不是可选的?

jOOλ 未检查

龙目岛@SneakyThrows

科特林 ;)

这篇关于如何在java 8流上使用foreach循环进行迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆