一 需求
以 name phone city三个字段为关键字,分组计算 area和money的和。
name | phone | city | area | money |
tom | 15687675434 | 北京 | 100 | 99.0 |
tom | 15687675434 | 北京 | 50 | 49.0 |
tom | 13654345654 | 上海 | 77 | 76.0 |
jerry | 15976543454 | 苏州 | 30 | 69.0 |
erry | 15976543454 | 苏州 | 40 | 99.0 |
二 算法分析
这里采用逐步求解的方法。
第一步:以 name phone city三个字段为分组字段,计算 area 的和,结果保存到list1。此时列表中的 money 字段为空。
第二步:以 name phone city三个字段为分组字段,计算 money 的和,结果保存到list2。此时列表中 area 字段为空。
第三步:将 list2 中的 money 拷贝到 list1 的 money 中去。
三 代码
package com.cakin.javademo;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @ClassName: GroupManyToMany
* @Description: 多字段分组,多字段求和
* @Date: 2021/3/14
* @Author: cakin
*/
public class GroupManyToMany {
/**
* 功能描述:多字段分组,单字段求和 测试
*
* @author cakin
* @date 2021/3/14
* @param args 命令行
*/
public static void main(String[] args) {
List<Person> users = new ArrayList<>();
users.add(new Person("tom", "15687675434", "北京", 100l,99.0));
users.add(new Person("tom", "15687675434", "北京", 50l,49.0));
users.add(new Person("tom", "13654345654", "上海", 77l,76.0));
users.add(new Person("jerry", "15976543454", "苏州", 70l,69.0));
users.add(new Person("jerry", "15976543454", "苏州", 100l,99.0));
// 第一步:以 name phone city 三个字段为分组字段,计算 area 的和。
List<Person> userList = new ArrayList<>();
users.stream().collect(Collectors
.groupingBy(user -> new Person(user.getName(), user.getPhone(), user.getCity()), Collectors.summarizingLong(user -> user.getArea())))
.forEach((k, v) -> {
k.setArea(v.getSum());
userList.add(k);
});
// 第二步:以 name phone city 三个字段为分组字段,分组计算 money 的和。
List<Person> userList1 = new ArrayList<>();
users.stream().collect(Collectors
.groupingBy(user -> new Person(user.getName(), user.getPhone(), user.getCity()), Collectors.summarizingDouble(user -> user.getMoney())))
.forEach((k, v) -> {
k.setMoney(v.getSum());
userList1.add(k);
});
// 第三步:将 userList1 中的 money 拷贝到 userList中
for (int i = 0; i < userList1.size(); i++) {
userList.get(i).setMoney(userList1.get(i).getMoney());
}
for (Person person : userList) {
System.out.println(person);
}
}
}
/**
* @ClassName: Person
* @Description: person类
* @Date: 2021/3/13
* @Author: cakin
*/
class Person {
/**
* 姓名
*/
public String name;
/**
* 手机
*/
public String phone;
/**
* 城市
*/
public String city;
/**
* 房屋面积
*/
public Long area;
/**
* 房屋总价
*/
public Double money;
public Person(String name, String phone, String city) {
this.name = name;
this.phone = phone;
this.city = city;
}
public Person(String name, String phone, String city, Long area,Double money) {
this.name = name;
this.phone = phone;
this.city = city;
this.area = area;
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Long getArea() {
return area;
}
public void setArea(Long area) {
this.area = area;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", phone='" + phone + '\'' +
", city='" + city + '\'' +
", area=" + area +
", money=" + money +
'}';
}
@Override
public int hashCode() {
return Objects.hash(name, phone, city);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) &&
Objects.equals(phone, person.phone) &&
Objects.equals(city, person.city) &&
Objects.equals(area, person.area) &&
Objects.equals(money, person.money);
}
}
四 测试
User{name='tom', phone='15687675434', city='北京', area=150, money=148.0}
User{name='jerry', phone='15976543454', city='苏州', area=170, money=168.0}
User{name='tom', phone='13654345654', city='上海', area=77, money=76.0}
五 说明
该算法比较笨拙,如果有更多的字段求和,就不可行了,还有更好的算法,在下一篇再介绍。