Это не работает с коллектором groupingBy
, так как он работает, передавая элементы, принадлежащие группе, нижестоящему коллектору каждой группы, и вы не можете сказать ему пропускать другие.
Oneспособ достижения того, что вы описали, это
TreeMap<Resource, Set<Resource>> map
= new TreeMap<>(Comparator.comparing(Resource::getSubnet));
for(Resource resource: resourceList)
map.computeIfAbsent(resource, x -> new HashSet<>(resourceList)).remove(resource);
map.forEach((resource,set) -> System.out.println(resource+" -> "
+set.stream().map(Resource::toString).collect(Collectors.joining(", "))));
, который, учитывая список S1R1, S1R2, S2R1, S2R2, S3R1, S3R2
, произведет
S1R1 -> S3R2, S2R1, S2R2, S3R1
S2R1 -> S3R2, S1R2, S3R1, S1R1
S3R1 -> S1R2, S2R1, S2R2, S1R1
, тогда как порядок элементов Set
равенundefined, ключи Map
фактически не выбираются случайным образом, это первый встреченный ресурс каждой подсети.
Это можно сделать с помощью двух операций цепочки потоков
Map<Resource, Set<Resource>> map = resourceList.stream()
.collect(Collectors.groupingBy(Resource::getSubnet, Collectors.toSet()))
.values().stream()
.collect(Collectors.toMap(
set -> set.iterator().next(),
set -> {
Set<Resource> other = new HashSet<>(resourceList);
other.removeAll(set);
return other;
}));
Здесьресурс, выбранный из каждой группы, действительно не указан.В отличие от подхода, основанного на TreeMap
, вам нужно знать фактический Resource
(или попробовать их все), чтобы найти группу.TreeMap
позволяет искать группу, используя любой Resource
из той же подсети.