#java #java-stream
Вопрос:
Допустим, есть следующий класс
class A {
B b
}
И у меня есть инициалы Map<A, List<C>>
.
Как я могу сгруппировать A по b и получить Map<B, Map<A, List<C>>>
?
Комментарии:
1. Это было бы что-то вроде
collect(toMap(A::getB, Function.identity()))
.2. Какая версия Java?
3. Пожалуйста, проясните вашу конкретную проблему или предоставьте дополнительные сведения, чтобы точно указать, что вам нужно. Поскольку это написано в настоящее время, трудно точно сказать, о чем вы просите.
Ответ №1:
Я не уверен Map<B, Map<A, List<C>>>
, что это имеет смысл в качестве вывода. Но вы можете попробовать что-то вроде:
myAMap.keySet().stream().reduce(new HashMap<B, List<A>>(), (map, key) -> {
if(map.get(key.b) == null) map.set(key.b, [key]);
else if(map.get(key.b) != null) map.set(key.b, map.get(key.b).add(key));
return map;
}),
Ответ №2:
Вы можете сделать это с помощью Java 9 (требуется для entry()
и flatMapping()
):
Map<B, Map<A, List<C>>> result = map.entrySet()
.stream()
.map(e -> Map.entry(e.getKey().b, Map.entry(e.getKey(), e.getValue().stream())))
.collect(groupingBy(Entry::getKey,
mapping(Entry::getValue,
groupingBy(Entry::getKey,
flatMapping(Entry::getValue, toList())))));
Это не очень приятное чтение, я знаю. Может быть, вы сможете добиться большего успеха с StreamEx.
Ответ №3:
На самом деле, я бы отказался от потоков и воспользовался другими новыми возможностями в интерфейсе карты.
- проверьте computeIfAbsent и putIfAbsent
Сначала создайте экземпляр целевой карты.
Map<B, Map<A, List<C>>> result = new HashMap<>();
- выполните итерацию по входному набору исходной карты.
- если нужного ключа нет, создайте запись с a
HashMap
, в противном случае используйте существующийHashMap
. - затем, если существующий ключ отсутствует, поместите его во внутреннюю карту вместе с исходным значением.
for (Map.Entry<A, List<C>> e : sourceMap.entrySet()) {
result.computeIfAbsent(e.getKey().b, v->new HashMap<>())
.putIfAbsent(e.getKey(), e.getValue());
}