Stream streams use grouping By + mapping to transform a set of objects after grouping into a set of attributes of an object

Keywords: Java Attribute Lambda Fragment

JAVA8 Actual Warfare Introduction to this fragment:

 

Java 8 Stream provides us with a convenient grouping collector by which we can easily group according to the value of an attribute of each element of an object set. After grouping common usage, the entire set of objects is divided into groups of the number of values of the attributes we select. That is to say, if we select the attribute A of each element object in the object set AList to be grouped, and there are three values of A, then the final AList will be divided into three groups. The set of elements in each group corresponds to the set of attributes A with values of 1, 2 and 3 respectively.

It may be somewhat circumscribed, for example:

There is a person class:

public class Person {

    /**
     * Name
     */
    private String name;
    /**
     * Gender
     */
    private String sex;
    /**
     * Age
     */
    private Integer age;

    @Override
    public String toString() {
        return String.format("[name:%s,sex:%s,age:%d]", name, sex, age);
    }

    public Person(String name, String sex, Integer age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

Then create a new test class:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class testMain {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        // Four small partners participating in the test
        Person tom = new Person("tom", "male", 11);
        Person amy = new Person("amy", "female", 13);
        Person ali = new Person("ali", "male", 12);
        Person daming = new Person("daming", "male", 13);
        personList.add(tom);
        personList.add(amy);
        personList.add(ali);
        personList.add(daming);
        // Grouping small partners according to gender age
        Map<String, List<Person>> resultMap = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        System.out.println(resultMap.toString());
    }

}

Operation results:

Then we get a map. The key of the map is all the values of the attribute sex we selected to group. value is a List set consisting of all elements whose sex attribute values in the PersonList set are equal to the current key (the object of the set element is a person type).

Well, next, we want to still group by gender and get the names of all the partners in each group, not all the information.

At this point, we need to use the second parameter of groupingBy, which can accept all types of collectors. Here, we use the mapping collector to meet our needs. The mapping collector basically has the same function as the map in the stream intermediate operation.

 

The mapping collector receives two parameters:

The first parameter is the lambda expression, which is used for attribute conversion.

The second parameter is a collector that collects the results of lambda expressions that aggregate the first parameter.

 

Let's modify the test class so that the final grouping result contains only the name of the small partner, not all the information of the small partner.

1. First of all, we need to modify the type of data received by grouping stream, from Map < String, List < Person > to Map < String, Set < String >, the reason why we use Set is to repeat the names of small partners.

2. Add a second parameter for groupingBy, a mapping collector. The first parameter of the mapping collector is the method reference Person::getName to get the name of the small partner. The second parameter is Collectors.toSet(), which assembles the name of each small partner obtained by the first parameter Person::getName into a Set set.

The modified test class code is as follows:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class testMain {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        // Four small partners participating in the test
        Person tom = new Person("tom", "male", 11);
        Person amy = new Person("amy", "female", 13);
        Person ali = new Person("ali", "male", 12);
        Person daming = new Person("daming", "male", 13);
        personList.add(tom);
        personList.add(amy);
        personList.add(ali);
        personList.add(daming);
        // Grouping small partners according to gender age
        Map<String, Set<String>> resultMap = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.mapping(Person::getName, Collectors.toSet())));
        System.out.println(resultMap.toString());
    }

}

The results are as follows:

Posted by DJ Unique on Wed, 24 Apr 2019 14:45:34 -0700