将具有相似属性的 Person 对象合并到一个 Map Entry 中
Merge Person objects with similar attributes into a single Map Entry
Person.java
class Person{
String name;
Integer age;
Integer salary;
//...getter..setter
}
Person 对象列表:
List<Person> tempList = new ArrayList<>(List.of(new Person("John",33,10000), new Person("Peter",21,2000), new Person("John",18,5000), new Person("Peter",31,6000)));
使用 java 流,如何告诉我的程序 'Find all person with same name and perform SUM operations on their Ages and on their Salaries'
所以期望的结果是这样的:
"John", 51, 1500
"Peter", 52, 8000
我尝试过的:
Map<String,Integer> NameAndSalary= tempList.stream().collect(Collectors.groupingBy(Person::getName,Collectors.summingInt(Person::getSalary) ));
Map<String,Integer> NameAndAge= tempList.stream().collect(Collectors.groupingBy(Person::getName,Collectors.summingInt(Person::getAge) ));
这很好,但这会产生单独的结果,例如:
"John", 51
和
"John", 1500
有没有捷径可以做到:
"John", 51, 1500
正如我在评论中提到的,Java 没有元组。创建元组的方法是创建一个类似于元组的 class 。 Person
class 已经类似于一个元组。所以,我所做的是创建一个 Java 记录(与 Java POJO 相同,减去了样板代码),我收集了同名的人并总结了他们的年龄和薪水以创建一个组合同名的人。我的解决方案:
public class TupleDemo {
public static void main(String[] args) {
List<Person> persons = List.of(
new Person("John",33,10000),
new Person("Peter",21,2000),
new Person("John",18,5000),
new Person("Peter",31,6000));
Collection<Person> result = persons.stream().collect(Collectors.groupingBy(p -> p.name(),
Collectors.collectingAndThen(
Collectors.reducing((Person p1, Person p2) -> new Person(p1.name(), p1.age() + p2.age(), p1.salary() + p2.salary())),
Optional::get))).values();
result.forEach(person ->{
System.out.println("Cumulative person: " + person);
});
}
private static record Person(String name, int age, int salary){
@Override
public String toString() {
return "Name: " + name + ", age: " + age + ", salary: " + salary;
}
}
}
这输出:
Cumulative person: Name: John, age: 51, salary: 15000
Cumulative person: Name: Peter, age: 52, salary: 8000
代码正在做的是使用一个流来收集,按名称分组,所有 Person
对象,并将创建一个新的 Person
由上一个匹配项和当前匹配项组成,其中保留名称属性,并将年龄和薪水相加。它将继续这样做,直到流被完全消耗掉。因此,对于这个示例,如果您要添加一个年龄为 48 岁且薪水为 12000 的新“Peter”,它将创建一个年龄为 100 且薪水为 20000 的“复合”Peter。
Person.java
class Person{
String name;
Integer age;
Integer salary;
//...getter..setter
}
Person 对象列表:
List<Person> tempList = new ArrayList<>(List.of(new Person("John",33,10000), new Person("Peter",21,2000), new Person("John",18,5000), new Person("Peter",31,6000)));
使用 java 流,如何告诉我的程序 'Find all person with same name and perform SUM operations on their Ages and on their Salaries'
所以期望的结果是这样的:
"John", 51, 1500
"Peter", 52, 8000
我尝试过的:
Map<String,Integer> NameAndSalary= tempList.stream().collect(Collectors.groupingBy(Person::getName,Collectors.summingInt(Person::getSalary) ));
Map<String,Integer> NameAndAge= tempList.stream().collect(Collectors.groupingBy(Person::getName,Collectors.summingInt(Person::getAge) ));
这很好,但这会产生单独的结果,例如:
"John", 51
和
"John", 1500
有没有捷径可以做到:
"John", 51, 1500
正如我在评论中提到的,Java 没有元组。创建元组的方法是创建一个类似于元组的 class 。 Person
class 已经类似于一个元组。所以,我所做的是创建一个 Java 记录(与 Java POJO 相同,减去了样板代码),我收集了同名的人并总结了他们的年龄和薪水以创建一个组合同名的人。我的解决方案:
public class TupleDemo {
public static void main(String[] args) {
List<Person> persons = List.of(
new Person("John",33,10000),
new Person("Peter",21,2000),
new Person("John",18,5000),
new Person("Peter",31,6000));
Collection<Person> result = persons.stream().collect(Collectors.groupingBy(p -> p.name(),
Collectors.collectingAndThen(
Collectors.reducing((Person p1, Person p2) -> new Person(p1.name(), p1.age() + p2.age(), p1.salary() + p2.salary())),
Optional::get))).values();
result.forEach(person ->{
System.out.println("Cumulative person: " + person);
});
}
private static record Person(String name, int age, int salary){
@Override
public String toString() {
return "Name: " + name + ", age: " + age + ", salary: " + salary;
}
}
}
这输出:
Cumulative person: Name: John, age: 51, salary: 15000
Cumulative person: Name: Peter, age: 52, salary: 8000
代码正在做的是使用一个流来收集,按名称分组,所有 Person
对象,并将创建一个新的 Person
由上一个匹配项和当前匹配项组成,其中保留名称属性,并将年龄和薪水相加。它将继续这样做,直到流被完全消耗掉。因此,对于这个示例,如果您要添加一个年龄为 48 岁且薪水为 12000 的新“Peter”,它将创建一个年龄为 100 且薪水为 20000 的“复合”Peter。