Java 8 - 如何对列表映射中的所有列表元素求和
Java 8 - How to sum all List element in a Map of Lists
我有一个特定对象的列表映射,我想添加基于特定实例变量的列表的所有元素。
我的对象:
class Risk{
Integer id, riskValue, totRisk=0;
String name;
Integer getId(){
return id;
}
Risk(Object[] result){
id=(Integer)result[0];
riskValue=(Integer)result[1];
name=(String)result[3];
}
}
我从数据库中得到一个对象类型的数组列表:
List< Object[] > results=getResults();
我使用 Java 8 按 ID 对我的数据进行分组,因为我想 SUM riskValue
所有 [=15= 类型的对象] 具有相同的 id
。
我就是这样做的:
List<Risk> risks=results.stream().map(Risk::new).collect(Collectors.toList());
Map<Integer, List<Risk>> byId=risks.stream.collect(Collectors.groupingBy(Risk::getId));
此时我已将所有 Risk 对象按 ID 分组。我希望每个列表按 riskValue
对所有对象求和,并将总数放在变量 totRisk
中
如何在变量totRisk
中计算每个List中变量riskValue
的总和?
注1:我想用Java8来做,我知道如何用Java7及以下来做。
注意 2:或许也可以一次完成,不必先按 ID 分组。我想实现的是将原List<Object[]> results
中所有具有相同ID的对象求和。如果能只用一条语句就更好了
你必须知道你可以组合 Collector
s。参见 Collectors.groupingBy(Function,Collector)
Map<Integer, Integer> byId=risks.stream.collect(
Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue)));
也可以结合第一个操作:
Map<Integer, Integer> byId=results.stream().map(Risk::new).collect(
Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue)));
请注意,我假设您的 class Risk
中有一个方法 getRiskValue()
,否则您必须将 Risk::getRiskValue
替换为 lambda 表达式 r -> r.riskValue
访问该字段,但是,始终建议使用 getter 方法。
结果从 id 映射到 total。
再次阅读您的问题后,我注意到您实际上想要总结 riskValue
并将其存储在 每个 的 totRisk
中(?)Risk
实例。这有点复杂,因为它不符合常见的使用模式:
Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect(
Collectors.groupingBy(Risk::getId, Collectors.collectingAndThen(
Collectors.toList(), l-> {
int total=l.stream().collect(Collectors.summingInt(r -> r.riskValue));
l.forEach(r->r.totRisk=total);
return l;
})));
此时我们真的应该改用 import static java.util.stream.Collectors.*;
:
Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect(
groupingBy(Risk::getId, collectingAndThen(toList(), l-> {
int total=l.stream().collect(summingInt(r -> r.riskValue));
l.forEach(r->r.totRisk=total);
return l;
})));
我有一个特定对象的列表映射,我想添加基于特定实例变量的列表的所有元素。
我的对象:
class Risk{
Integer id, riskValue, totRisk=0;
String name;
Integer getId(){
return id;
}
Risk(Object[] result){
id=(Integer)result[0];
riskValue=(Integer)result[1];
name=(String)result[3];
}
}
我从数据库中得到一个对象类型的数组列表:
List< Object[] > results=getResults();
我使用 Java 8 按 ID 对我的数据进行分组,因为我想 SUM riskValue
所有 [=15= 类型的对象] 具有相同的 id
。
我就是这样做的:
List<Risk> risks=results.stream().map(Risk::new).collect(Collectors.toList());
Map<Integer, List<Risk>> byId=risks.stream.collect(Collectors.groupingBy(Risk::getId));
此时我已将所有 Risk 对象按 ID 分组。我希望每个列表按 riskValue
对所有对象求和,并将总数放在变量 totRisk
如何在变量totRisk
中计算每个List中变量riskValue
的总和?
注1:我想用Java8来做,我知道如何用Java7及以下来做。
注意 2:或许也可以一次完成,不必先按 ID 分组。我想实现的是将原List<Object[]> results
中所有具有相同ID的对象求和。如果能只用一条语句就更好了
你必须知道你可以组合 Collector
s。参见 Collectors.groupingBy(Function,Collector)
Map<Integer, Integer> byId=risks.stream.collect(
Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue)));
也可以结合第一个操作:
Map<Integer, Integer> byId=results.stream().map(Risk::new).collect(
Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue)));
请注意,我假设您的 class Risk
中有一个方法 getRiskValue()
,否则您必须将 Risk::getRiskValue
替换为 lambda 表达式 r -> r.riskValue
访问该字段,但是,始终建议使用 getter 方法。
结果从 id 映射到 total。
再次阅读您的问题后,我注意到您实际上想要总结 riskValue
并将其存储在 每个 的 totRisk
中(?)Risk
实例。这有点复杂,因为它不符合常见的使用模式:
Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect(
Collectors.groupingBy(Risk::getId, Collectors.collectingAndThen(
Collectors.toList(), l-> {
int total=l.stream().collect(Collectors.summingInt(r -> r.riskValue));
l.forEach(r->r.totRisk=total);
return l;
})));
此时我们真的应该改用 import static java.util.stream.Collectors.*;
:
Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect(
groupingBy(Risk::getId, collectingAndThen(toList(), l-> {
int total=l.stream().collect(summingInt(r -> r.riskValue));
l.forEach(r->r.totRisk=total);
return l;
})));