我有一张地图:Map<String, Map<String, String>> x
我想计算第二张地图中的值总和:
x.values().stream().mapToDouble(y -> Double.parse(y.get("myKey"))).sum();
但是如果y.get(“myKey”)不是有效数字,它将按预期抛出错误...有没有办法可以避免它并只传递有效数字
我看到来自guava库的Doubles.tryParse会返回null,因为它不可解析。但我无法弄清楚如何使用它来只加总有效数字。
答案 0 :(得分:5)
无需使用第三方库,只需抓住NumberFormatException
:
double sum = x.values().stream().mapToDouble(y -> {
try {
return Double.parseDouble(y.get("myKey"));
} catch (NumberFormatException e) {
return 0.0;
}
}).sum();
如果忽略缺少值,您也可以抓住RuntimeException
,而不是导致NullPointerException
。
答案 1 :(得分:4)
Doubles.tryParse()
如果失败则返回null。以下是您如何利用这一优势:
x.values()
.stream()
.map(y -> Doubles.tryParse(y.get("myKey")))
.filter(Objects::nonNull) // exclude invalid numbers
.mapToDouble(Double::doubleValue)
.sum();
答案 2 :(得分:2)
这些通过使用RegEx进行预过滤来避免引发/捕获异常(我可能会对此进行此操作,但在反射 我不确定这对双打是否合理 由于格式复杂性。)
不介意提出异常?见:#45873009
使用番石榴了吗?请参阅:#45873075
x.values()
.stream()
.map(m -> m.get("myKey"))
.filter(s -> s.matches(Numbers.DOUBLE_FORMAT)) // you'll want a constant...
.mapToDouble(Double::parseDouble)
.sum();
x.values()
.stream()
.map(m -> m.get("myKey"))
.mapToDouble(Numbers::parseDoubleOrDefault) // default 0.0 doesn't affect sum...
.sum();
x.values()
.stream()
.map(m -> m.get("myKey"))
.flatMapToDouble(Numbers::tryParseDouble)
.sum();
public class Numbers {
// Extensive regex! Thank you @Andreas & Oracle Docs
// https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-
private static final String DIGITS = "(\\p{Digit}+)";
private static final String HEX_DIGITS = "(\\p{XDigit}+)";
private static final String EXPONENT = "[eE][+-]?"+ DIGITS;
public static final String DOUBLE_FORMAT = "[\\x00-\\x20]*[+-]?(NaN|Infinity|((("+ DIGITS +"(\\.)?("+ DIGITS +"?)("+ EXPONENT +")?)|(\\.("+ DIGITS +")("+ EXPONENT +")?)|(((0[xX]" + HEX_DIGITS + "(\\.)?)|(0[xX]" + HEX_DIGITS + "?(\\.)" + HEX_DIGITS + "))[pP][+-]?" + DIGITS + "))[fFdD]?))[\\x00-\\x20]*";
public double parseDoubleOrDefault(final String input, final double defaultValue) {
return input.matches(DOUBLE_FORMAT)
? Double.parseDouble(input)
: defaultValue;
}
public double parseDoubleOrDefault(final String input) {
return parseDoubleOrDefault(0.0);
}
// Stream because Java 8 flatMap doesn't work on Optional
public DoubleStream tryParseDouble(final String input) {
return input.matches(DOUBLE_FORMAT)
? DoubleStream.of(Double.parseDouble(input))
: DoubleStream.empty();
}
}