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

hen*_*xin 8 java for-loop exception java-8 java-stream

在下面的代码,当捕NumberFormatException出来的for迭代,以适当的形式字符串出现在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);  
}
Run Code Online (Sandbox Code Playgroud)

然而,当更换for的迭代stream()或者parallelStream(),我失去了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);  
}
Run Code Online (Sandbox Code Playgroud)

什么是从内部抛出的异常的控制流的规格stream()parallelStream()

我怎样才能得到结果intList = [1,2](即忽略第一次NumberFormatException抛出之后的结果)或甚至更好intList = [1,2,4,6](即忽略坏的结果NumberFormatException)stream()或者parallelStream()

And*_*niy 8

为什么不直接包裹lambda-body try...catch

您还可以nullmap以下情况后过滤值:

    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());
Run Code Online (Sandbox Code Playgroud)

这会给你想要的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());
Run Code Online (Sandbox Code Playgroud)

或者为了避免使用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());
Run Code Online (Sandbox Code Playgroud)

  • @Andremoniy我为长篇编辑道歉.我开始的时候会更短. (2认同)
  • @PeterLawrey我很荣幸能和你有这样的合作答案:) (2认同)
  • @PeterLawrey`Option`是避免`null`的另一种选择. (2认同)