首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用流处理异常

使用流处理异常
EN

Stack Overflow用户
提问于 2019-10-02 20:51:27
回答 4查看 705关注 0票数 9

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

代码语言:javascript
复制
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()))
               );

我的主要问题是每个String可能不能正确地表示一个Long;可能会有一些问题。Long::valueOf可能会引发异常。如果是这种情况,我希望返回一个null或空Map<String,List<Long>>

因为我想遍历这个output映射。但我不能接受任何错误转换;甚至不能接受一个错误转换。你知道如何在不正确的字符串->长转换的情况下返回一个空输出吗?

EN

回答 4

Stack Overflow用户

发布于 2019-10-02 21:05:13

在异常上显式的catch如何:

代码语言:javascript
复制
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();
    }
}
票数 4
EN

Stack Overflow用户

发布于 2019-10-03 00:40:02

我个人喜欢提供一个围绕数字解析的Optional输入:

代码语言:javascript
复制
public static Optional<Long> parseLong(String input) {
    try {
        return Optional.of(Long.parseLong(input));
    } catch (NumberFormatException ex) {
        return Optional.empty();
    }
}

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

代码语言:javascript
复制
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()))
               );

此外,考虑一个helper方法,使其更简洁:

代码语言:javascript
复制
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());
}

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

代码语言:javascript
复制
Map<String, List<Long>> converted = input.entrySet().stream()
    .collect(Collectors.toMap(Entry::getKey, MyClass::convertEntry));

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

但是,如果您希望完全不对任何坏的输入进行操作,那么在您试图捕获的整个流中包围整个流(根据Naman的答案)是我会采取的路线。

票数 4
EN

Stack Overflow用户

发布于 2019-10-02 23:58:28

您可以为异常的密钥创建StringBuilder,并检查ele是否为数字,如下所示。

代码语言:javascript
复制
 public static Map<String, List<Long>> transformInput(Map<String, List<String>> input) {
    StringBuilder sb = new StringBuilder();
    try {
    return input.entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream()
                    .map(ele->{
                        if (!StringUtils.isNumeric(ele)) {
                            sb.append(e.getKey()); //add exception key
                            throw new NumberFormatException();
                        }
                        return Long.valueOf(ele);
                    })
                    .collect(Collectors.toList())));
} catch (NumberFormatException nfe) {
    System.out.println("Exception key "+sb);
    return Collections.emptyMap();
}
}

希望能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58201890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档