提问人:AntonBoarf 提问时间:10/2/2019 最后编辑:TylerHAntonBoarf 更新时间:5/27/2021 访问量:1688
处理流的异常
Handling exceptions with streams
问:
我有一个并希望它变成,因为列表中的每个都代表一个: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()))
);
我的主要问题是每个都可能无法正确表示一个;可能存在一些问题。 可能会引发异常。如果是这种情况,我想返回 null 或空String
Long
Long::valueOf
Map<String,List<Long>>
因为我想在这张地图上迭代。但我不能接受任何错误转换;甚至没有一个。关于在不正确的 String -> Long 转换的情况下如何返回空输出的任何想法?output
答:
如何显式处理异常: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();
}
}
评论
nfe.getMessage()
input.entrySet().stream() .filter(e -> e.getValue().stream().anyMatch(s -> !new Scanner(s).hasNextLong())) .map(Map.Entry::getKey) .findAny()
您可以创建一个有异常的 for 键,并检查是否为数字,如下所示,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();
}
}
希望它有所帮助。
我个人喜欢提供有关数字解析的输入: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
但是,如果您的愿望是完全不对任何错误的输入进行操作,那么将整个流包围在你试图捕获的内容中(根据 Naman 的回答)是我会采取的路线。
也许你可以编写一个辅助方法,可以检查字符串中的数字,并将它们从流和空值中过滤掉,然后最终收集到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());
}
评论
LongStream
empty