将List<Object>转换为Map<String, Map<String,List<Object>>>。

12

我有一个 List<Person>,其中 Person 如下。

class Person {

    String personId;
    LocalDate date;
    String type;

    // getters & setters

}

我正在尝试将此转换为List<Person>Map<String, Map<LocalDate,List<Person>>>,其中外部map的键是personId,内部map的键是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也在外部声明? - M. Prokhorov
可能是将嵌套列表转换为嵌套映射的重复问题。 - Hadi J
3个回答

17
list.stream()
    .collect(Collectors.groupingBy(
        Person::getPersonId,
        Collectors.groupingBy(
            Person::getDate
)));

7

这个答案展示了如何使用流来实现,另一个答案则展示了如何使用传统的迭代方法。以下是另一种方式:

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方法,如果outerMap中不存在(以personId为键),则创建一个新的innerMap并将其添加到outerMap中;同时,如果innerMap中不存在(以date为键),则创建一个新的innerList并将其添加到innerMap中。最后,将Person对象添加到innerList中。


2
很高兴了解Map.computeIfAbsent。谢谢Federico! - Ram

3
你的for循环组织应该改变,以便在创建新列表之前尝试从嵌套映射中获取现有的List<Person>。这是一个两步过程:
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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接