为了账号安全,请及时绑定邮箱和手机立即绑定

使用流处理异常

使用流处理异常

白板的微信 2023-09-20 14:38:17
我有一个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()))               );我的主要问题是每个都String可能无法正确代表Long; 可能有一些问题。Long::valueOf可能会引发异常。如果是这种情况,我想返回 null 或空Map<String,List<Long>>因为我想迭代这张output地图。但我不能接受任何错误的转换;连一个也没有。知道如何在 String -> Long 转换不正确的情况下返回空输出吗?
查看完整描述

4 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

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


public static Optional<Long> parseLong(String input) {

    try {

        return Optional.of(Long.parseLong(input));

    } catch (NumberFormatException ex) {

        return Optional.empty();

    }

}

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


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()))

               );

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


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());

}

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


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


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


查看完整回答
反对 回复 2023-09-20
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

显式地处理异常怎么样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();

    }

}


查看完整回答
反对 回复 2023-09-20
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

您可以创建一个StringBuilderfor 键(但有例外)并检查是否ele为数字,如下所示,


 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();

}

}

希望能帮助到你。


查看完整回答
反对 回复 2023-09-20
?
慕斯王

TA贡献1864条经验 获得超2个赞

也许您可以编写一个辅助方法,该方法可以检查字符串中的数字并从流中过滤掉它们以及空值,然后最终收集到 Map 中。


// StringUtils.java

public static boolean isNumeric(String string) {

    try {

        Long.parseLong(string);

        return true;

    } catch(NumberFormatException e) {

        return false;

    }

}

这会照顾一切。


并在您的信息流中使用它。


Map<String, List<Long>> newMap = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> mapToLongValues(entry.getValue())));


public List<Long> mapToLongValues(List<String> strs) {

    return strs.stream()

        .filter(Objects::nonNull)

        .filter(StringUtils::isNumeric)

        .map(Long::valueOf)

        .collect(Collectors.toList());

}


查看完整回答
反对 回复 2023-09-20
  • 4 回答
  • 0 关注
  • 114 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信