Ответ 1
list.stream()
.collect(Collectors.groupingBy(
Person::getPersonId,
Collectors.groupingBy(
Person::getDate
)));
У меня есть List<Person>
где Person
выглядит следующим образом.
class Person {
String personId;
LocalDate date;
String type;
// getters & setters
}
Я пытаюсь преобразовать это в List<Person>
в Map<String, Map<LocalDate,List<Person>>>
где внешний ключ карты - это 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);
}
list.stream()
.collect(Collectors.groupingBy(
Person::getPersonId,
Collectors.groupingBy(
Person::getDate
)));
Этот ответ показывает, как сделать это с потоками, а другой - как сделать это с помощью традиционного итеративного подхода. Вот еще один способ:
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
и поместить его в innerMap
если нет (ключ - date
). Наконец, Person
добавляется во innerList
.
Ваша 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);
}