通过聚合和分组将一个对象映射到另一个对象
我上课
class Q {
String username;
int taskId;
double timediff;
// constructor
}
,我需要将其转换为
class ToQ {
String username;
int noOfTasks;
double sum;
// constructor
}
因此,意图是按用户名分组,不计算taskId,timediff之和。
此列表
List<Q> qs = new ArrayList<>();
qs.add(new Q("tom", 2, 2.0));
qs.add(new Q("tom", 6, 1.0));
qs.add(new Q("harry", 8, 0.03));
ToQ的输出应为
new ToQ("tom",2,3);
new ToQ("harry",1,0.03);
我尝试使用分组功能,但是它会生成HashMap,但不确定如何转换为对象。
Map<String, Double> collect = qs
.stream()
.collect(groupingBy(Q::getUsername, summingDouble(Q::getLocalDateTime)));
答案 0 :(得分:3)
此可能可以通过toMap
收集器更好地完成:
Collection<ToQ> values = qs.stream().collect(toMap(Q::getUsername,
v -> new ToQ(v.getUsername(), 1, v.getTimediff()),
(l, r) -> {
l.setNoOfTasks(l.getNoOfTasks() + r.getNoOfTasks());
l.setSum(l.getSum() + r.getSum());
return l;
})).values();
这假定您具有一个Q
构造函数,如下所示:
public ToQ(String username, int noOfTasks, double sum) {...}
如果您希望坚持使用groupingBy
,则可以执行以下操作:
List<ToQ> result = qs.stream()
.collect(groupingBy(Q::getUsername))
.values()
.stream()
.map(l -> new ToQ(l.get(0).getUsername(), l.size(), l.stream().mapToDouble(Q::getTimediff).sum()))
.collect(toList());
答案 1 :(得分:1)
您可以按照以下步骤进行操作:
Map<String, Double> nameToTimeDiffSumMap = qs.stream()
.collect(Collectors.groupingBy(Q::getUsername,
Collectors.summingDouble(Q::getTimediff)));
Map<String, Long> nameToCountMap = qs.stream()
.collect(Collectors.groupingBy(Q::getUsername,
Collectors.counting()));
List<ToQ>
List<ToQ> toQS = qs.stream().map(a ->
new ToQ(a.getUsername(), nameToCountMap.get(a.getUsername()), nameToTimeDiffSumMap.get(a.getUsername())))
.collect(toList());
假定这些类具有 getters 和 setters 以及适当的 constructor
class ToQ {
String username;
long noOfTasks;
double sum;
}
class Q {
String username;
int taskId;
double timediff;
}
答案 2 :(得分:1)
简单的方法是这样的:将toMap()
与合并功能一起使用。
Map<String, ToQ> map = qs.stream()
.collect(toMap(Q::getUsername, q -> new ToQ(q.username, q.taskId, q.timediff), ToQ::merge));
List<ToQ> toQList = new ArrayList<>( map.values());
并在ToQ中定义一个方法:
public ToQ merge(ToQ q){
this.noOfTasks+=q.noOfTasks;
this.sum+=q.sum;
return this;
}
答案 3 :(得分:0)
您也可以使用一个衬纸来尝试:
List<ToQ> toQS = qs.stream()
.map(Q::getUserName)
.distinct()
.map(userName -> new ToQ(
userName,
qs.stream()
.map(Q::getUserName)
.filter(userName::equals)
.count(),
qs.stream()
.map(Q::getUserName)
.filter(q -> Objects.equals(userName, q.getUserName()))
.mapToDouble(Q::getTimeDiff)
.sum()
))
.collect(toList())