【问题标题】:Java - Convert list of objects to map of map data structureJava - 将对象列表转换为地图数据结构的地图
【发布时间】:2020-06-03 12:04:00
【问题描述】:

我正在尝试将对象数据结构列表转换为地图。

Map<String, Map<Integer, StudentModel>>

字符串是运动变量

整数是 orderId。

我的逻辑返回值低于如下所示。我正在寻找更好的方法来实现这一目标。

@Data
@Builder
public class Student {    
    private String name;
    private int rollno;
    private int studentage;
    private String sports;
    private int orderId;
}   

@Data
@Builder
public class StudentModel {
    private String name;
    private int rollno;
    private int studentage;
    private String sports;
}

创建相同的数据并添加到列表中:

arraylist.add(new Student(223, "Zebra", 26, "cricket", 1));
arraylist.add(new Student(245, "Rahul", 24, "cricket", 2));
arraylist.add(new Student(209, "Ajeet", 32, "cricket", 3));
arraylist.add(new Student(140, "Abhay", 28, "basketball", 4));
arraylist.add(new Student(270, "Ranger", 29, "basketball", 5));
arraylist.add(new Student(250, "Ranger1", 39, "basketball",6));
Collections.sort(arraylist, Comparator.comparing(Student::getOrderId));

我的预期输出:

{
 cricket={
     1=Student(sports=cricket, rollno=223, name=Zebra, studentage=26), 
     2=Student(sports=cricket, rollno=245, name=Rahul, studentage=24), 
     3=Student(sports=cricket, rollno=209, name=Ajeet, studentage=32)
     }, 
 basketball={
     4=Student(sports=basketball, rollno=140, name=Abhay, studentage=28), 
     5=Student(sports=basketball, rollno=270, name=Ranger, studentage=29), 
     6=Student(sports=basketball, rollno=250, name=Ranger1, studentage=39)
     }
 }

逻辑写法:

public Map<String, Map<Integer, StudentModel>> studentModel() {
    Map<Integer, StudentModel> studentMap = new LinkedHashMap<>();
    Map<String, Map<Integer, StudentModel>> inputMap = new LinkedHashMap<>();
    for (Student student : arraylist) {
        StudentModel studentModel = StudentModel.builder().name(student.getName)
        .rollno(student.getRollno)
        .studentage(student.getStudentage)
        .sports(student.getSports)
        studentMap.put(studentModel.getOrderId, studentModel);
        inputMap.put(student.getSports, studentMap);
    }
 }

上面的逻辑返回下面的结果:

 {
 cricket={
     1=Student(sports=cricket, rollno=223, name=Zebra, studentage=26), 
     2=Student(sports=cricket, rollno=245, name=Rahul, studentage=24), 
     3=Student(sports=cricket, rollno=209, name=Ajeet, studentage=32),
     4=Student(sports=basketball, rollno=140, name=Abhay, studentage=28), 
     5=Student(sports=basketball, rollno=270, name=Ranger, studentage=29), 
     6=Student(sports=basketball, rollno=250, name=Ranger1, studentage=39)
     }, 
 basketball={
     1=Student(sports=cricket, rollno=223, name=Zebra, studentage=26), 
     2=Student(sports=cricket, rollno=245, name=Rahul, studentage=24), 
     3=Student(sports=cricket, rollno=209, name=Ajeet, studentage=32),
     4=Student(sports=basketball, rollno=140, name=Abhay, studentage=28), 
     5=Student(sports=basketball, rollno=270, name=Ranger, studentage=29), 
     6=Student(sports=basketball, rollno=250, name=Ranger1, studentage=39)
     }
 }

【问题讨论】:

  • 问题是什么?
  • 我的代码预期输出和实际输出不同
  • 检查预期输出:以上逻辑返回以下结果:以上代码中的值

标签: java arraylist linkedhashmap


【解决方案1】:

问题是您对inputMap 的每个条目仅使用studentMap 的单个实例/内存,因此您会看到每个“运动”键的所有6 个学生条目,因为每个inputMap 条目值都指向到studentMap 的相同参考值,从而观察任何运动类型键所做的更改。

您在这里要做的是为每种“运动”类型创建studentMap 的新内存,所以。您可以尝试这样做:

public Map<String, Map<Integer, StudentModel>> studentModel() {

    Map<Integer, StudentModel> studentMap;
    Map<String, Map<Integer, StudentModel>> inputMap = new LinkedHashMap<>();
    for (Student student : arraylist) {
        StudentModel studentModel = StudentModel.builder().name(student.getName)
        .rollno(student.getRollno)
        .studentage(student.getStudentage)
        .sports(student.getSports)

        // This would create new memory for each type of sport
        studentMap = inputMap.getOrDefault(student.getSports, new LinkedHashMap<Integer, StudentModel>());
        studentMap.put(studentModel.getOrderId, studentModel);
        inputMap.put(student.getSports, studentMap);
    }
 }

【讨论】:

  • 酷。这对我有用。谢谢 你能解释一下“你对 inputMap 的每个条目只使用一个studentMap的实例/内存”是什么意思吗
  • @sudhir 我的意思是所有 inputMap 值都指向 Map 的相同引用,因为显然 studentMap 只创建了一次。因此,每当 studentMap 更新时,无论我们在哪里使用它,它的引用都会开始反映这些变化。结果,针对每种运动类型,输出有 6 条学生记录。
  • 知道了。谢谢
【解决方案2】:

您需要为每项运动创建一张新地图:

public Map<String, Map<Integer, StudentModel>> studentModel() {
    Map<String, Map<Integer, StudentModel>> inputMap = new LinkedHashMap<>();
    for (Student student : arraylist) {
        StudentModel studentModel = StudentModel.builder().name(student.getName)
        .rollno(student.getRollno)
        .studentage(student.getStudentage)
        .sports(student.getSports)
        // create a new map and insert it into the outer map if it's not already there
        Map<Integer, StudentModel> studentMap = inputMap.computeIfAbsent(student.getSports, k -> new LinkedHashMap<>());
        studentMap.put(studentModel.getOrderId, studentModel);
    }
 }

与问题无关,但应使用 getter 方法访问字段,例如而不是 student.getSports 你应该有一个私有的 sports 字段和一个 getSports() 方法。

【讨论】:

    【解决方案3】:

    groupingBy 方法完全符合您的需要。您想根据他们的运动对原始数组列表中的学生进行分组:

    Map<String, List<Student>> inputMap = arraylist.stream().collect(Collectors.groupingBy(Student::getSports));
    

    【讨论】:

      【解决方案4】:

      发生这种情况是因为您在两个类别中使用相同的学生地图实例。

      这是你的代码

       public Map<String, Map<Integer, StudentModel>> studentModel() {
          Map<Integer, StudentModel> studentMap = new LinkedHashMap<>();
          Map<String, Map<Integer, StudentModel>> inputMap = new LinkedHashMap<>();
          for (Student student : arraylist) {
              StudentModel studentModel = StudentModel.builder().name(student.getName)
                      .rollno(student.getRollno)
                      .studentage(student.getStudentage)
                      .sports(student.getSports)
              studentMap.put(studentModel.getOrderId, studentModel);//logical error here
              inputMap.put(student.getSports, studentMap);//error here
          }
      }
      

      使用下面的代码获得所需的结果

      public Map<String, Map<Integer, StudentModel>> studentModel() {
          Map<Integer, StudentModel> studentMap = new LinkedHashMap<>();
          Map<String, Map<Integer, StudentModel>> inputMap = new LinkedHashMap<>();
          for (Student student : arraylist) {
              if (inputMap.get(student.getSports())==null){
                  studentMap = new LinkedHashMap<>();
              }else{
                  studentMap = inputMap.get(student.getSports());
              }
              StudentModel studentModel = StudentModel.builder().name(student.getName)
                      .rollno(student.getRollno)
                      .studentage(student.getStudentage)
                      .sports(student.getSports)
              studentMap.put(studentModel.getOrderId, studentModel);//error here
              inputMap.put(student.getSports, studentMap);//error here
          }
      }`
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-22
        • 1970-01-01
        • 2021-03-18
        • 2019-12-05
        • 2017-09-02
        • 2021-04-06
        相关资源
        最近更新 更多