【问题标题】:List<Object> to Map<String, Map<String,List<Object>>>List<Object> 到 Map<String, Map<String,List<Object>>>
【发布时间】:2018-09-22 18:48:58
【问题描述】:

我有List&lt;Person&gt;,其中Person 如下。

class Person {

    String personId;
    LocalDate date;
    String type;

    // getters & setters

}

我正在尝试将其转换为List&lt;Person&gt;Map&lt;String, Map&lt;LocalDate,List&lt;Person&gt;&gt;&gt;,其中外部映射的键是personId,内部映射的键是date,我不知道如何实现这一点。 到目前为止,已经尝试过类似下面的东西。也对 Java 8 解决方案开放。

Map<String,Map<LocalDate,List<Person>>> outerMap = new HashMap<>();
Map<LocalDate,List<Person>> innerMap = new HashMap<>();

for(Person p : list) {
    List<Person> innerList = new ArrayList<>();
    innerList.add(p);
    innerMap.put(p.getDate(), innerList);
    outerMap.put(p.getPersonId(), innerMap);
}

【问题讨论】:

  • 你应该解释你的想法。为什么在循环内声明innerList?为什么innerMap 声明在外面?为什么outerMap 也在外面声明?

标签: java list collections java-8 hashmap


【解决方案1】:

This answer 展示了如何使用流来实现,this other one 展示了如何使用传统的迭代方法来实现。这是另一种方式:

Map<String, Map<LocalDate, List<Person>>> outerMap = new HashMap<>();
list.forEach(p -> outerMap
        .computeIfAbsent(p.getPersonId(), k -> new HashMap<>()) // returns innerMap
        .computeIfAbsent(p.getDate(), k -> new ArrayList<>())   // returns innerList
    .add(p)); // adds Person to innerList

这使用Map.computeIfAbsent创建一个新的innerMap,如果不存在则放入outerMap(键为personId),同时创建一个新的innerList并放入@ 987654330@ 如果不存在(键是date)。最后,将Person 添加到innerList

【讨论】:

  • 很高兴知道Map.computeIfAbsent。谢谢费德里科!
【解决方案2】:

您的for 循环组织应更改为尝试从嵌套映射中获取现有List&lt;Person&gt;,然后再继续创建新列表。这是一个两步过程:

Map<String,Map<LocalDate,List<Person>>> outerMap = new HashMap<>();
for(Person p : list) {
    Map<LocalDate,List<Person>> innerMap = outerMap.get(p.getPersonId());
    if (innerMap == null) {
        innerMap = new HashMap<>();
        outerMap.put(p.getPersonId(), innerMap);
    }
    List<Person> innerList = innerMap.get(p.getDate());
    if (innerList == null) {
        innerList = new ArrayList<>();
        innerMap.put(p.getDate(), innerList);
    }
    innerList.add(p);
}

【讨论】:

    【解决方案3】:
    list.stream()
        .collect(Collectors.groupingBy(
            Person::getPersonId,
            Collectors.groupingBy(
                Person::getDate
    )));
    

    【讨论】:

      猜你喜欢
      • 2020-08-01
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      • 2010-10-05
      • 2018-04-26
      • 1970-01-01
      相关资源
      最近更新 更多