Java8GroupBy一个字段,然后映射到多个字段

Java8GroupBy一个字段,然后映射到多个字段,java,java-8,Java,Java 8,我有一个对象结构,比如 class Person{ String userId; String firstName; String lastName; Set<Courses> courses = new HashSet<Courses>(); } 从数据库将结果检索到列表resultSet 现在,我需要按userId分组,然后将课程映射到集合中,并创建一个列表对象 现在我可以按用户ID分组并将课程收集到集合中,但无法映射firstName和la

我有一个对象结构,比如

class Person{
   String userId;
   String firstName;
   String lastName;
   Set<Courses> courses = new HashSet<Courses>();
}
从数据库将结果检索到
列表resultSet

现在,我需要按userId分组,然后将课程映射到集合中,并创建一个
列表
对象

现在我可以按用户ID分组并将课程收集到集合中,但无法映射firstName和lastName

Map<Object, Set<Object>> userList = resultSet.stream().collect()
.Collectors.groupingBy( usr -> usr.get("user_id"),
     Collectors.mapping( usr -> usr.get("courses"), Collectors.toSet()) ));

// Result {user1=[course1, course2, course3]}
Map userList=resultSet.stream().collect()
.Collectors.groupingBy(usr->usr.get(“用户id”),
Collectors.mapping(usr->usr.get(“课程”),Collectors.toSet());
//结果{user1=[course1,course2,course3]}
然后我创建Person对象

List<Person> = userList.entrySet.stream().
              .map( usr -> new Person(usr.getKey().toString(),
                               (Set<Courses)(Set<?>)usr.getValue()))
              .collect(Collectors.toList())
List=userList.entrySet.stream()。
.map(usr->newperson(usr.getKey().toString(),

(设置您可以使用
收集器.toMap
而不是
收集器.groupingBy
。您将通过传递到
toMap
的合并函数实现分组

它将创建一些不必要的
Person
实例,但最终结果将包含您想要的内容

Map<String,Person> persons = 
    resultSet.stream()
             .collect(Collectors.toMap(usr -> usr.get("user_id"),
                                       usr -> new Person(usr.get("user_id"),usr.get("first_name"),usr.get("last_name"),usr.get("course")),
                                       (p1,p2)->{p1.addCourses(p2.getCourses()); return p1;}));
映射人员=
resultSet.stream()
.collect(Collectors.toMap(usr->usr.get(“用户id”),
usr->新人(usr.get(“用户id”)、usr.get(“名字”)、usr.get(“姓氏”)、usr.get(“课程”),
(p1,p2)->{p1.addCourses(p2.getCourses());返回p1;});

这是假设您在Word类中有相关的构造函数和方法.

您也可以尝试将您的自定义收集器定义为下游函数传递给<代码>收藏家.GuangPin By.()<代码> >考虑下面的例子:

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class PersonGroupByExample {

    public static void main(String[] args) {

        final List<Map<String, Object>> input = Arrays.asList(
                new HashMap<String, Object>(){{
                    put("userId", "user1");
                    put("firstName", "John");
                    put("lastName", "Smith");
                    put("courses", "course1");
                }},
                new HashMap<String, Object>(){{
                    put("userId", "user1");
                    put("firstName", "John");
                    put("lastName", "Smith");
                    put("courses", "course2");
                }},
                new HashMap<String, Object>(){{
                    put("userId", "user1");
                    put("firstName", "John");
                    put("lastName", "Smith");
                    put("courses", "course3");
                }},
                new HashMap<String, Object>(){{
                    put("userId", "user2");
                    put("firstName", "Jack");
                    put("lastName", "Smith");
                    put("courses", "course1");
                }},
                new HashMap<String, Object>(){{
                    put("userId", "user2");
                    put("firstName", "Jack");
                    put("lastName", "Smith");
                    put("courses", "course2");
                }}
        );

        final Collection<Person> result = input.stream()
                .parallel()
                .collect(Collectors.groupingBy(it -> it.get("userId"), Collector.of(
                        // Start with an empty Person object
                        Person::new,
                        // Collect a list of map objects grouped by the same userId into a single Person object
                        (person, map) -> {
                            // Override common properties
                            person.setUserId(map.getOrDefault("userId", "").toString());
                            person.setFirstName(map.getOrDefault("firstName", "").toString());
                            person.setLastName(map.getOrDefault("lastName", "").toString());
                            // Add person's course to a courses set
                            person.getCourses().add(new Course(map.getOrDefault("courses", "").toString()));
                        },
                        // Combiner function that join partials results (for parallel execution)
                        (person, person2) -> {
                            person.getCourses().addAll(person2.getCourses());
                            return person;
                        }
                ))).values();

        result.forEach(System.out::println);
    }


    static class Person {
        String userId;
        String firstName;
        String lastName;
        Set<Course> courses = new HashSet<>();

        public Person() {}

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        public Set<Course> getCourses() {
            return courses;
        }

        public void setCourses(Set<Course> courses) {
            this.courses = courses;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "userId='" + userId + '\'' +
                    ", firstName='" + firstName + '\'' +
                    ", lastName='" + lastName + '\'' +
                    ", courses=" + courses +
                    '}';
        }
    }

    static class Course {
        String id;

        public Course(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "Course{" +
                    "id='" + id + '\'' +
                    '}';
        }
    }
}

你应该使用还原法

Map<String, Person> people = userList = resultSet.stream()
    .map(v -> toPerson())
    .collect(groupingBy(Person::getId, reducing(null, (p1, p2) -> {
          p1.getCourses().addAll(p2.getCourses); 
          return p1;
    })));
其思想是使用单个
课程集
的Person对象映射每一行,然后分组并缩小

Map<String, Person> people = userList = resultSet.stream()
    .map(v -> toPerson())
    .collect(groupingBy(Person::getId, reducing(null, (p1, p2) -> {
          p1.getCourses().addAll(p2.getCourses); 
          return p1;
    })));
Map people=userList=resultSet.stream()
.map(v->toPerson())
.collect(groupbyperson::getId,reduced(null,(p1,p2)->{
p1.getCourses().addAll(p2.getCourses);
返回p1;
})));

希望您能理解。

结果集的类型是什么?结果集的类型是List是来自dbOh的查询结果,但是否可以像我试图学习的那样使用groupingbyit@RinsenS我不确定。它的性能要好一点
(p1,p2)->{if(p1.getCourses().size()>p2.getCourses().size())){p1.getCourses().addAll(p2.getCourses());返回p1;}其他{p2.getCourses().addAll(p1.getCourses());返回p2;}
非常感谢您的回答,但我没有将输入用户列为列表。我将输入列为列表,这使得它必须获得课程和设置对象,您能在这方面提供帮助吗…@RinsenS我已经更新了示例以使用
列表
作为输入。太棒了,我刚刚完成。也感谢您的解决方案
Map<String, Person> people = userList = resultSet.stream()
    .map(v -> toPerson())
    .collect(groupingBy(Person::getId, reducing(null, (p1, p2) -> {
          p1.getCourses().addAll(p2.getCourses); 
          return p1;
    })));