【问题标题】:Collect a list of ids based on multiple fields收集基于多个字段的id列表
【发布时间】:2021-03-11 03:24:56
【问题描述】:

我有一个包含 personId、年龄和性别的人员对象。

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));

我想创建一个这样的临时对象,其中包含年龄、性别和学生 ID 列表。

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

现在,我想创建带有年龄、性别和学生 ID 列表的 TempObject。这个对象应该有一对年龄、性别和与年龄和性别对应的学生ID列表。有人可以帮我吗。我尝试过使用 java8 的分组方式。

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]);

【问题讨论】:

  • 这能回答你的问题吗? Group by multiple field names in java 8
  • @VladL 在发布我的问题之前,我已经尝试过此代码。在该示例中,用户试图让 Person 对象列表与一对。但我需要获取具有年龄和性别对的 studentIds 列表。

标签: java list collections java-stream grouping


【解决方案1】:

您可以使用Collectors.toMap(keyMapper,valueMapper,mergeFunction,mapFactory) 方法收集TreeMap 按两个字段比较的重复项:agegender,并合并 ids 到列表中:

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]

另见:Sort List<Map<String,Object>> based on value

【讨论】:

    【解决方案2】:

    你可以在这里观看非常好的guide

    无论如何,我希望它对你有帮助(也许有点)。

    主类

    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;
        }
    
    }
    

    临时对象

    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());
        }
    }
    

    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);
        }
     }
    

    您可以使用此行过滤您的列表

    persons.stream()              
    .collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getGender)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多