简体   繁体   English

基于另一个 ArrayList 添加或更新 ArrayList 的元素

[英]Add or Update elements of an ArrayList based on another ArrayList

I have two ArrayLists of ClassRoom object and below shows the ClassRoom class:我有两个ClassRoom object 的 ArrayLists,下面显示了ClassRoom class:

public class ClassRoom {

    private String className; // className is unique here
    private List<Student> students = new ArrayList<>();

    public ClassRoom(String className, List<Student> students) {
        this.className = className;
        this.students = students;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {

        String ss = "[";
        for (int i = 0; i < students.size(); i++) {
            ss += "{name:'" + students.get(i).getName() + "',age:" + students.get(i).getAge() + "}";
            ss += (i == (students.size() - 1)) ? "" : ",";
        }
        ss += "]";
        return "{'" + className + "':" + ss + "}";
    }

}

ClassRoom class contains className String property and List of Student object which describes below: ClassRoom class 包含className String 属性和Student object 列表,描述如下:

public class Student {

    private String name; // name is unique here
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

}

I have created my two lists of ClassRoom object like below:我已经创建了两个ClassRoom object 列表,如下所示:

List<ClassRoom> list1 = new ArrayList<>();

list1.add(new ClassRoom("A", Arrays.asList(new Student("Sam", 20), new Student("Peter", 40), new Student("Aaron", 15))));
list1.add(new ClassRoom("B", Arrays.asList(new Student("Ronnie", 33), new Student("Daniel", 41), new Student("Gabe", 35))));
list1.add(new ClassRoom("C", Arrays.asList(new Student("Fabian", 42), new Student("Edgar", 33))));
list1.add(new ClassRoom("D", Arrays.asList(new Student("Peter", 39), new Student("Calvin", 45))));

List<ClassRoom> list2 = new ArrayList<>();

list2.add(new ClassRoom("A", Arrays.asList(new Student("Sam", 26), new Student("Aaron", 18))));
list2.add(new ClassRoom("B", Arrays.asList(new Student("Daniel", 38), new Student("Eddy", 29))));
list2.add(new ClassRoom("C", Arrays.asList(new Student("Fabian", 42), new Student("Edgar", 33))));

So my final task is to create a new List of ClassRoom object like below:所以我的最后一项任务是创建一个新的ClassRoom列表,如下所示:

List<ClassRoom> mergedList = merge(list1, list2);

for (ClassRoom classRoom : mergedList) {
    System.out.println(classRoom.toString());
    /* Expected output here
    {'A':[{name:'Sam',age:26},{name:'Peter',age:40},{name:'Aaron',age:18}]}
    {'B':[{name:'Ronnie',age:33},{name:'Daniel',age:38},{name:'Gabe',age:35},{name:'Eddy',age:29}]}
    {'C':[{name:'Fabian',age:42},{name:'Edgar',age:33}]}
    {'D':[{name:'Peter',age:39},{name:'Calvin',age:45}]}
   */
}

And below explains my merge method:下面解释了我的merge方法:

public static List<ClassRoom> merge(List<ClassRoom> listA, List<ClassRoom> listB) {

      ArrayList<ClassRoom> collect = Stream.of(listA, listB).collect(ArrayList<ClassRoom>::new, (item1, item2) -> {
          item2.forEach((c2) -> {
            item1.forEach((c1) -> {
                if (c2.getClassName().equalsIgnoreCase(c1.getClassName())) {
                    // Student list update goes here
                } else {
                    item1.add(c2);
                }
            });
        });
      }, (item1, item2) -> {

      });

    return collect;
 }

Problem I am having so far is resulting an empty list after the merge method call.到目前为止我遇到的问题是在合并方法调用后产生一个空列表。 Any suggestions would be appreciated.任何建议,将不胜感激。

  1. Override the equals and hashCode methods in Student on name .name上覆盖Student中的equalshashCode方法。
@Override
public boolean equals(Object obj) {
    return Objects.equals(name, ((Student) obj).getName());
}

@Override
public String toString() {
    return "name: " + name + ", age: " + age;
}
  1. Override the equals and hashCode methods in ClassRoom using the default implementation suggested by your IDE.使用 IDE 建议的默认实现覆盖ClassRoom中的equalshashCode方法。
  2. Collect list2 into a Map<String, List<Student>> map and process each element of list1 as shown below:list2收集成一个Map<String, List<Student>> map ,对list1的每个元素进行如下处理:

Map<String, List<Student>> map = list2.stream()
            .collect(Collectors.toMap(ClassRoom::getClassName, ClassRoom::getStudents));

list1.forEach(e -> map.merge(e.getClassName(),
                                Stream.of(map.getOrDefault(e.getClassName(), e.getStudents()), e.getStudents())
                                .flatMap(List::stream)
                                .distinct()
                                .collect(Collectors.toList()),
                                    (v1, v2) -> v2)
                            );

Output: Output:

{A=[name: Sam, age: 26, name: Aaron, age: 18, name: Peter, age: 40], B=[name: Daniel, age: 38, name: Eddy, age: 29, name: Ronnie, age: 33, name: Gabe, age: 35], C=[name: Fabian, age: 42, name: Edgar, age: 33], D=[name: Peter, age: 39, name: Calvin, age: 45]} {A=[姓名:Sam,年龄:26,姓名:Aaron,年龄:18,姓名:Peter,年龄:40],B=[姓名:Daniel,年龄:38,姓名:Eddy,年龄:29,姓名: Ronnie,年龄:33,姓名:Gabe,年龄:35],C=[姓名:Fabian,年龄:42,姓名:Edgar,年龄:33],D=[姓名:Peter,年龄:39,姓名:Calvin,年龄:45]}

ONLINE DEMO在线演示

You can do like this:你可以这样做:

public static List<ClassRoom> merge(List<ClassRoom> listA, List<ClassRoom> listB) {
    Map<String, Set<Student>> map = new HashMap<>();
    listA.forEach(item -> map.put(item.getClassName(), new HashSet<>(item.getStudents())));
    for (ClassRoom classRoom : listB) {
        Set<Student> set = map.getOrDefault(classRoom.getClassName(), new HashSet<>());
        set.addAll(classRoom.getStudents());
        map.put(classRoom.getClassName(), set);
    }
    List<ClassRoom> list = new ArrayList<>();
    map.forEach((k, v) -> list.add(new ClassRoom(k, new ArrayList<>(v))));
    return list;
}

and add below in Student:并在学生中添加以下内容:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Student)) return false;
    Student student = (Student) o;
    return getName() != null ? getName().equals(student.getName()) : student.getName() == null;
}
@Override
public int hashCode() {
    return getName() != null ? getName().hashCode() : 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM