Java 8 groupby one field and then maps to multiple fields

I have an object structure like this

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

The database record is like this (in fact, the users firstname and LastName are from another table, but for simplicity, I will be as follows):

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

Retrieve the results from the database to the list < map < string, Object > > result set

Now I need to group by userid, then map the course to set and create a list < person > object

Now I can group by userid and collect courses into the collection, but I can't map firstname and 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]}

Then I'm creating a person object

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

How do I get firstname, LastName in the grouping by step and use it to create objects?

Solution

You can also try to define a custom collector passed as a downstream function to collectors groupingBy(). Consider the following examples:

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() groups all entries by userid field, and then uses the downstream function of the custom collector to reduce the list of map < string, Object > Entries grouped by the same userid contain a single person instance of all courses I use person and course POJO to describe the process, and also enter list < map < string, Object > > to describe the conversion process

Finally, we call map The values () method returns collection < person > instead of map < string, person >

Running this sample will create the following output:

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'}]}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>