微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java 8 GroupBy一个字段然后映射到多个字段

我有一个像这样的对象结构

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

数据库记录是这样的(实际上用户firstName和lastName来自另一个表,但为了简单起见,我将如下所示):

user1 John  Smith course1 
user1 John  Smith course2
user1 John  Smith course3
user2 Jack  Smith course1
user2 Jack  Smith course2

数据库中检索结果到List< Map< String,Object>>结果集.

现在我需要按userId进行分组,然后将课程映射到Set并创建一个List< Person>对象.

现在我能够通过userId进行分组并将课程收集到集合中但不能映射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]}

然后我正在创建Person Object

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

如何在groupingby步骤中获取firstName,lastName并使用它来创建对象?

解决方法

您还可以尝试将作为下游函数传递的自定义收集器定义到Collectors.groupingBy().考虑以下示例:

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,"course2");
                }},"course3");
                }},"user2");
                    put("firstName","Jack");
                    put("lastName","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 + '\'' +
                    '}';
        }
    }
}

Collectors.groupingBy()按userId字段对所有条目进行分组,然后使用自定义收集器的下游函数减少Map< String,Object>的列表.由同一userId分组的条目包含所有课程的单个Person实例.我使用Person和Course POJO来说明流程,也输入List< Map< String,Object>>用于说明转换过程.

最后,我们调用Map.values()方法返回Collection< Person>而不是Map< String,Person>.

运行此示例将创建以下输出

Person{userId='user1',firstName='John',lastName='Smith',courses=[Course{id='course1'},Course{id='course3'},Course{id='course2'}]}
Person{userId='user2',firstName='Jack',courses=[Course{id='course2'},Course{id='course1'}]}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐