使用流处理异常

Ant*_*arf 10 java java-8 java-stream

我有一个,Map<String,List<String>>并希望将其变成,Map<String,List<Long>>因为String列表中的每个代表一个Long

Map<String,List<String>> input = ...;
Map<String,List<Long>> output= 
input.entrySet()
       .stream()
       .collect(toMap(Entry::getKey, e -> e.getValue().stream()
                                                      .map(Long::valueOf)
                                                      .collect(toList()))
               );
Run Code Online (Sandbox Code Playgroud)

我主要的问题是每个人String可能不能正确代表一个Long; 可能有一些问题。Long::valueOf可能会引发例外。如果是这种情况,我想返回一个null或空Map<String,List<Long>>

因为我想遍历这张output地图。但是我不能接受任何错误转换。甚至没有一个。关于如何在不正确的String-> Long转换的情况下如何返回空输出的任何想法?

Rog*_*gue 5

我个人喜欢提供Optional有关数字解析的输入:

public static Optional<Long> parseLong(String input) {
    try {
        return Optional.of(Long.parseLong(input));
    } catch (NumberFormatException ex) {
        return Optional.empty();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,使用您自己的代码(并忽略错误的输入):

Map<String,List<String>> input = ...;
Map<String,List<Long>> output= 
input.entrySet()
       .stream()
       .collect(toMap(Entry::getKey, e -> e.getValue().stream()
                                                      .map(MyClass::parseLong)
                                                      .filter(Optional::isPresent)
                                                      .map(Optional::get)
                                                      .collect(toList()))
               );
Run Code Online (Sandbox Code Playgroud)

此外,考虑一个辅助方法来使其更加简洁:

public static List<Long> convertList(List<String> input) {
    return input.stream()
        .map(MyClass::parseLong).filter(Optional::isPresent).map(Optional::get)
        .collect(Collectors.toList());
}

public static List<Long> convertEntry(Map.Entry<String, List<String>> entry) {
    return MyClass.convertList(entry.getValue());
}
Run Code Online (Sandbox Code Playgroud)

然后您可以在流收集器中过滤结果:

Map<String, List<Long>> converted = input.entrySet().stream()
    .collect(Collectors.toMap(Entry::getKey, MyClass::convertEntry));
Run Code Online (Sandbox Code Playgroud)

您还可以将空Optional对象保留在列表中,然后通过将新对象List<Optional<Long>>(而不是List<Long>)中的索引与原始对象进行比较List<String>,您可以找到导致任何错误输入的字符串。您也可以简单地将这些失败记录在MyClass#parseLong

但是,如果您的愿望是根本不对任何不良输入进行操作,那么我将采取的路线是围绕您试图捕获的整个流(根据纳曼的回答)。


Nam*_*man 4

显式地处理异常怎么样catch

private Map<String, List<Long>> transformInput(Map<String, List<String>> input) {
    try {
        return input.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream()
                        .map(Long::valueOf)
                        .collect(Collectors.toList())));
    } catch (NumberFormatException nfe) {
        // log the cause
        return Collections.emptyMap();
    }
}
Run Code Online (Sandbox Code Playgroud)