我有一个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映射。但我不能接受任何错误转换;甚至不能接受一个错误转换。你知道如何在不正确的字符串->长转换的情况下返回一个空输出吗?
发布于 2019-10-02 21:05:13
在异常上显式的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();
}
}发布于 2019-10-03 00:40:02
我个人喜欢提供一个围绕数字解析的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()))
);此外,考虑一个helper方法,使其更简洁:
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中
但是,如果您希望完全不对任何坏的输入进行操作,那么在您试图捕获的整个流中包围整个流(根据Naman的答案)是我会采取的路线。
发布于 2019-10-02 23:58:28
您可以为异常的密钥创建StringBuilder,并检查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();
}
}希望能有所帮助。
https://stackoverflow.com/questions/58201890
复制相似问题