Reputation: 127
I'm searching for an optimal or subpotimal solution for below problem:
Hp: We have a Java8 Map: Map<Integer, Object>: {0 -> object0, 1 -> object0, 2->object1, ...., n->objectN}
Goal: Solution to return a Map (a submap) that contains only key,value elements of original map with same objects: Map<Integer, Object>: {0 -> object0, 1 -> object0}
I found a solution to get a List of duplicate but I don't find a solution to get a new Map with only duplicated values.
Thanks for support
Upvotes: 2
Views: 579
Reputation: 19565
A straightforward solution would be:
Map<Object, List<Integer>>
flatMap
to restore initial Map<Integer, Object>
Map<Integer, Object> map = Map.of(
0, "object0", 1, "object0", 2, "objectA", 3, "objectZ", 4, "objectZ"
);
System.out.println(map);
Map<Integer, Object> filtered = map.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList())
))
.entrySet().stream() // Stream<Map.Entry<Object, List<Integer>>>
.filter(e -> e.getValue().size() > 1) // keep duplicates
.flatMap(e -> e.getValue().stream().map(v -> Map.entry(v, e.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println(filtered);
Output:
{0=object0, 1=object0, 2=objectA, 3=objectZ, 4=objectZ}
{0=object0, 1=object0, 3=objectZ, 4=objectZ}
Update
Simpler solution by @Andreas suggestion would be:
Map<Integer, Object> filtered2 = map.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue))
.entrySet().stream() // Stream<Map.Entry<Object, List<Map.Entry<Integer, Object>>>
.filter(e -> e.getValue().size() > 1) // keep duplicates
.flatMap(e -> e.getValue().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println(filtered2);
Output is the same as above:
{0=object0, 1=object0, 3=objectZ, 4=objectZ}
Upvotes: 1
Reputation: 7279
You can try this:
Map<Object, Map<String, Object>> subMaps =
map.entrySet()
.stream()
.collect(groupingBy(Map.Entry::getValue,
toMap(Map.Entry::getKey, Map.Entry::getValue)));
This will return you a map of maps.
So if you want the submap containing only object0
do this:
Map<String, Object> subMap = subMaps.get(object0);
If you are not interested in all the submaps, but looking for a specific value, then do this instead:
Map<String, Object> subMapForObject1 =
map.entrySet()
.stream()
.filter(e -> object1.equals(e.getValue());
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue)));
Upvotes: 2