1

I have a person object with personId, age and gender.

public class Person {
    private int personId;
    private int age;
    private int gender; // 0 for male and 1 for female
}
List<Person> person = new Arraylist<>();
person.add(new Person(1,1,1));
person.add(new Person(2,2,0));
person.add(new Person(3,10,1));
person.add(new Person(4,11,0));
person.add(new Person(5,20,1));
person.add(new Person(6,20,1));
person.add(new Person(7,2,0));
person.add(new Person(8,20,0));
person.add(new Person(9,11,0));
person.add(new Person(10,20,1));

I would like to create a temp object like this with age, gender and list of studentIds.

TempObject {
    private int age;
    private int gender;
    private List<Integer> studentIds;
}

Now, I want to create TempObject with with age, gender and list of studentIds. This object should have a pair of age, gender and list of student ids corresponding to age and gender. Can someone help me out. I have tried using java8's grouping by.

new TempObject(1,1,[1]);
new TempObject(2,0,[2,7]);
new TempObject(10,1,[3]);
new TempObject(11,0,[4,9]);
new TempObject(20,1,[5,6,10]);
new TempObject(20,0,[8]);
Sunil
  • 101
  • 1
  • 10
  • 2
    Does this answer your question? [Group by multiple field names in java 8](https://stackoverflow.com/questions/28342814/group-by-multiple-field-names-in-java-8) – Vlad L Nov 28 '20 at 17:54
  • @VladL I have tried this code before posting my question. In that example, user is trying to let list of Person objects with a pair. But i need to get list of studentIds with the pair of age and gender. – Sunil Nov 28 '20 at 18:14

2 Answers2

1

you can watch here for a very good guide

Anyway, i hope it helps you (maybe a little bit).

Main-Class

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

public class mainMethod {

    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person(1, 1, 1));
        persons.add(new Person(2, 2, 0));
        persons.add(new Person(3, 1, 1));
        persons.add(new Person(4, 11, 0));
        persons.add(new Person(5, 20, 1));
        persons.add(new Person(6, 20, 1));
        persons.add(new Person(7, 2, 0));
        persons.add(new Person(8, 20, 0));
        persons.add(new Person(9, 11, 0));
        persons.add(new Person(10, 20, 1));

        TempObjectMapper tempObjectMapper = new TempObjectMapper(persons.stream()
                .collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getGender))));

        List<TempObject> tempObjects = tempObjectMapper.getObjects();

        System.out.println(tempObjects.toString());
    }
}

TempObjectMapper

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

public class TempObjectMapper {

    private Map<Integer, Map<Integer, List<Person>>> map;

    public TempObjectMapper(Map<Integer, Map<Integer, List<Person>>> collect) {
        this.map = collect;
    }

    public List<TempObject> getObjects() {
        List<TempObject> list = new ArrayList<TempObject>();

        this.map.forEach((key, value) -> {
            int age = key;
            Map<Integer,List<Person>> map1 = value;

            map1.forEach((key1, value1) -> {
                int gender = key1;
                List<Person> person = value1;
                list.add(new TempObject(age, gender, person));
            });
        });
        return list;
    }

}

TempObject

import java.util.List;

public class TempObject {
 
    private int age;

    private int gender;

    private List<Person> persons;

    public TempObject(int age, int gender, List<Person> persons) {
        this.age = age;
        this.gender = gender;
        this.persons = persons;
    }

    @Override
    public String toString() {
        return String.format("TempObject: [%s,%s,%s]" , this.age, this.gender, this.persons.toString());
    }
}

Person

public class Person {
    private int personId;
    private int age;
    private int gender;  //0 for male and 1 for female

    public Person(int id, int age, int gender) {
        this.personId = id;
        this.age = age;
        this.gender = gender;
    }
    public int getPersonId() {
        return this.personId;
    }

    public int getAge() {
        return this.age;
    }

    public int getGender() {
        return this.gender;
    }

    @Override
    public String toString() {
        return String.format("Person: [%s, %s, %s]", this.personId,this.age,this.gender);
    }
 }

You can filter your list with this line

persons.stream()              
.collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getGender)))
Marcel Herhold
  • 166
  • 1
  • 7
0

You can use Collectors.toMap(keyMapper,valueMapper,mergeFunction,mapFactory) method to collect the TreeMap of duplicates comparing by two fields: age and gender, and merging ids to the list:

List<Person> persons = Arrays.asList(
        new Person(1, 1, 1),
        new Person(2, 2, 0),
        new Person(3, 10, 1),
        new Person(4, 11, 0),
        new Person(5, 20, 1),
        new Person(6, 20, 1),
        new Person(7, 2, 0),
        new Person(8, 20, 0),
        new Person(9, 11, 0),
        new Person(10, 20, 1));
ArrayList<TempObject> tempObjects =
        new ArrayList<>(persons.stream()
                // convert Person to TempObject
                .map(e -> new TempObject(e.getAge(), e.getGender(),
                        Collections.singletonList(e.getPersonId())))
                // collect a Map<TempObject, TempObject>
                .collect(Collectors.toMap(
                        // key of the map
                        Function.identity(),
                        // value of the map
                        Function.identity(),
                        // merge function
                        (to1, to2) -> {
                            // merging two lists of ids
                            to1.setStudentIds(List
                                    .of(to1.getStudentIds(), to2.getStudentIds())
                                    .stream()
                                    .flatMap(List::stream)
                                    .distinct()
                                    .collect(Collectors.toList()));
                            return to1;
                        },
                        // map factory - specify a comparator
                        // for duplicates by age and gender
                        () -> new TreeMap<>(Comparator
                                .comparing(TempObject::getGender)
                                .thenComparing(TempObject::getAge))))
                // get a Collection
                // of the values
                .values());
tempObjects.forEach(System.out::println);
// age=2, gender=0, studentIds=[2, 7]
// age=11, gender=0, studentIds=[4, 9]
// age=20, gender=0, studentIds=[8]
// age=1, gender=1, studentIds=[1]
// age=10, gender=1, studentIds=[3]
// age=20, gender=1, studentIds=[5, 6, 10]

See also: Sort List<Map<String,Object>> based on value