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

时间:2016-01-02 08:28:11

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

在以下代码中,从NumberFormatException次迭代中捕获for时,在第一个错误的strList之前出现"illegal_3"的相应形式的字符串(即"1")已成功解析(即"2"1已被解析为整数2public 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); } )。

for

但是,当stream()parallelStream()替换1次迭代时,我会失去2public 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); }

stream()
  

parallelStream()intList = [1,2]内引发的异常控制流程的规范是什么?

     

如何获得NumberFormatException的结果(即忽略第一个intList = [1,2,4,6]之后的结果)或更好NumberFormatException(即忽略stream()的结果parallelStream() 1}})CREATE SCHEMASQLDBSAMPLE

4 个答案:

答案 0 :(得分:8)

为什么不在try...catch中包裹lambda-body?

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

    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]

编辑:减少&#34;沉重&#34;在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());

答案 1 :(得分:2)

方法既不能返回值,也不能抛出异常。那是不可能的。

因此,您不能指望collect()返回列表并抛出异常。因为如果抛出异常,它就不能返回新的列表。

如果您的for循环代码实际上与流代码类似,那么您将遇到同样的问题:

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{
        intList = collectToIntegers(strList);
    } catch (NumberFormatException nfe) {
        System.err.println(nfe.getMessage());
    }

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

private List<Integer> collectToIntegers(List<String> strList) {
    List<Integer> result = new ArrayList<>();
    for (String str : strList) {
       result.add(Integer.parseInt(str));
    }
    return result;
}

简而言之:不要混淆“创建和返回新列表”,“获取列表并向其添加元素”。

答案 2 :(得分:1)

我不知道有多少次遇到过我只想忽略NumberFormatException的情况。我可能会创建一个单独的可重用方法来静默解析整数并返回OptionalInt值。

这是utils类

public class IntUtils {
    // ... other utility methods

    public static OptionalInt parseInt(String s, Consumer<? super Exception> exceptionConsumer) {
        try {
            return OptionalInt.of(Integer.parseInt(s));
        } catch (NumberFormatException e) {
            if (exceptionConsumer != null) {
                // let the caller take the decision
                exceptionConsumer.accept(e);
            } else {
                // default behavior
                e.printStackTrace();
            }
        }

        return OptionalInt.empty();
    }

    public static OptionalInt parseInt(String s) {
        return parseInt(s, null);
    }
}

这是测试方法

List<Integer> collect1 = strStream.map(str -> IntUtils.parseInt(str, Exception::printStackTrace))
            .filter(OptionalInt::isPresent)
            .map(OptionalInt::getAsInt).collect(toList());

// or 
List<Integer> collect2 = strStream.map(IntUtils::parseInt)
            .filter(OptionalInt::isPresent)
            .map(OptionalInt::getAsInt).collect(toList());

答案 3 :(得分:0)

我正在使用org.apache.commons.lang3.math.NumberUtils

.mapToInt(s -> NumberUtils.toInt(s, Integer.MIN_VALUE))
.filter(x -> x > Integer.MIN_VALUE)