I have a list of resource objects. Resource object is defined as:
class Resource {
String ip;
String subnet;
// other properties...
}
I need a datastrucutre like a map where the key is a random resource in one subnet and value is a list of all resources in other subnets.
For example, if S
denotes subnet and R
denotes resource, the list has:
S1R1, S1R2, S2R1, S2R2, S3R1 and S3R2
Expected output is:
S1R1 -> S2R1, S2R2, S3R1, S3R2
S2R2 -> S1R1, S1R2, S3R1, S3R2
S3R1 -> S1R1, S1R2, S2R1, S2R2
I tried using stream and collect which grouped based on subnets, not sure how to proceed from here.
Map<String, Set<Resource>> grouped = resourceList.stream()
.collect(Collectors.groupingBy(Resource::getSubnet, Collectors.toSet()));
This doesn't work with the groupingBy
collector, as it works by passing the elements belonging to a group to each group's downstream collector and you can't tell it to pass the others.
One way to achieve what you've described, is
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(", "))));
Which, given the list S1R1, S1R2, S2R1, S2R2, S3R1, S3R2
will produce
S1R1 -> S3R2, S2R1, S2R2, S3R1
S2R1 -> S3R2, S1R2, S3R1, S1R1
S3R1 -> S1R2, S2R1, S2R2, S1R1
while the order of the Set
's elements is undefined, the Map
's keys actually are not picked randomly, it's the first encountered resource of each subnet.
You could do this with two chained stream operations
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;
}));
Here, the resource picked from each group is indeed unspecified. Unlike the TreeMap
based approach, you would have to know the actual Resource
(or try them all) to lookup a group. The TreeMap
allows to lookup a group by using any Resource
from the same subnet.
I am not sure what how subnets work but you have to figure out the below relationship( isSubNetOf ).
BiPredicate<Resource, Resource> isSubNetOf = (parent, subnet) -> ???;
Map<Resource, Set<Resource>> resourceToSubnets = resourceList.stream()
.collect(toMap(
Function.identity(),
x -> resourceList.stream().filter(v -> isSubNetOf.test(x, v)).collect(toSet())
));
If you want a Map<String, Set<Resource>>
change Function.identity()
to the required Resource::getIp
or Resource::getSubnet
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.