java - 从 'stream()' 或 'parallelStream()' 中捕获异常会丢失正确的值

标签 java exception for-loop java-8 java-stream

在下面的代码中,当从 for 迭代中捕获 NumberFormatException 时,适当形式的字符串出现在 strList 中第一个坏字符串之前(即 "illegal_3")已成功解析(即 "1""2" 已解析为整数 12)。

public void testCaughtRuntimeExceptionOutOfIteration() {
    List<String> strList = Stream.of("1", "2", "illegal_3", "4", "illegal_5", "6").collect(Collectors.toList());
    List<Integer> intList = new ArrayList<>();

    try{
        for (String str : strList) {
            intList.add(Integer.parseInt(str));
        }
    } catch (NumberFormatException nfe) {
        System.err.println(nfe.getMessage());
    }

    List<Integer> expectedIntList = Stream.of(1, 2).collect(Collectors.toList());
    // passed
    assertEquals("The first two elements have been parsed successfully.", expectedIntList, intList);  
}

但是,当用 stream()parallelStream() 替换 for 迭代时,我丢失了 12

public void testCaughtRuntimeExceptionOutOfStream() {
    List<String> strList = Stream.of("1", "2", "illegal_3", "4", "illegal_5", "6").collect(Collectors.toList());
    List<Integer> intList = new ArrayList<>();

    try{
        intList = strList.stream()  // same with "parallelStream()"
                .map(Integer::parseInt)
                .collect(Collectors.toList());
    } catch (NumberFormatException nfe) {
        System.err.println(nfe.getMessage());
    }

    List<Integer> expectedIntList = Stream.of(1, 2).collect(Collectors.toList());
    // failed: expected:<[1,2]>, but was:<[]>
    assertEquals("The first two elements have been parsed successfully.", expectedIntList, intList);  
}

What is the specification of the control flow of exceptions thrown from within stream() or parallelStream()?

How can I get the result of intList = [1,2] (i.e., ignore the ones after the first NumberFormatException is thrown) or even better intList = [1,2,4,6] (i.e., ignore the bad ones with NumberFormatException) with stream() or parallelStream()

最佳答案

为什么不将 lambda 体包裹在 try...catch 中?

您还可以在 map 之后过滤 null 值:

    intList = strList.stream()// same with "parallelStream()"
            .map(x -> {
                try {
                    return Integer.parseInt(x);
                } catch (NumberFormatException nfe) {
                    System.err.println(nfe.getMessage());
                }
                return null;
            })
            .filter(x -> x!= null)
            .collect(Collectors.toList());

这将为您提供所需的 intList = [1,2,4,6]

编辑:要减少 lamdba 中 try/catch 的“重量”,您可以添加辅助方法。

static Integer parseIntOrNull(String s) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException nfe) {
        System.err.println(nfe.getMessage());
    }
    return null;
}

intList = strList.stream()
            .map(x -> parseIntOrNull(x))
            .filter(x -> x!= null)
            .collect(Collectors.toList());

或者为了避免使用null,你可以返回一个Stream

static Stream<Integer> parseIntStream(String s) {
    try {
        return Stream.of(Integer.parseInt(s));
    } catch (NumberFormatException nfe) {
        System.err.println(nfe.getMessage());
    }
    return Stream.empty();
}

intList = strList.stream()
            .flatMap(x -> parseIntStream(x))
            .collect(Collectors.toList());

关于java - 从 'stream()' 或 'parallelStream()' 中捕获异常会丢失正确的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34564025/

相关文章:

Java .read() 函数返回什么?和Java IOException

javascript - 当Java程序循环访问数千个数据时,如何显示最终用户可见的进度条?

c++ - "...redeclared as different kind of symbol"?

java - 如何使用 twitter4j 获取固定数量的推文

java - 使用 boolean 值同步

asp.net-mvc - 错误处理不起作用ASP .NET MVC

c++ - 用户输入字符串并计算字母实例的程序

java - @OneToMany 表关系中的冗余行数据或实体

java - hibernate : Lock a row while update, 所以用户不会从中检索计数器

c++ - 如何使用 boost 异常将信息添加到 std::exception