简体   繁体   中英

convert from Map<Object,Set<Object>> to Map<String,Set<String>>

I have a map Map<String, Set<String>>

Map<String, Set<String> result = map.entrySet().parallelStream().collect(
            Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));

I want to convert it to Map<String, Set<String>> . by grouping the values and swapping the places of key and value.

But this line gives me

Type mismatch: cannot convert from Map<Object,Set<Object>> to Map<String,Set<String>>

The problem that you've got here is the type of the map you are creating is:

Map<Set<String>, Set<String>>

not Map<String, Set<String>> .

As such, you need to expand the map's values first, for example:

Map<String, Set<String>> collect = map.entrySet()
    .parallelStream()
    // Expand (k, {v1, v2, v3}) to [(v1, k), (v2, k), (v3, k)]
    .flatMap(e -> e.getValue().stream().map(ee -> new SimpleEntry<>(ee, e.getKey())))
    .collect(
        Collectors.groupingBy(
            Map.Entry::getKey,
            Collectors.mapping(Map.Entry::getValue, Collectors.toSet())));

Unless you really need the parallel processing, I think it would be much easier to use loops:

Map<String, Set<String>> collect = new HashSet<>();
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
  for (String v : entry.values()) {
      collect.computeIfAbsent(v -> new HashSet<>())
              .add(entry.getKey()));
  }
}

Here is an example considering your initial Map is Object to Object. Adapt as needed.

Map<Object,Object> map = new HashMap<>();
Map<String, Set<String>> result = map
            .entrySet()
            .parallelStream()
            .collect(Collectors.groupingBy(entry -> (String) entry.getKey(), 
                     Collectors.mapping(entry -> (String) entry.getKey(), Collectors.toSet())));

The problem with your code is that Map.Entry::getKey returns an Object, not a String.

Just to avoid the confusion, I'm answering my question. Thanks to @AndyTurner @alexrolea for pointing out the solution.

Map<Set<String>, Set<String>> result = map.entrySet().parallelStream()
                .collect(
                Collectors.groupingBy(entry -> (Set<String>) entry.getValue(), 
                        Collectors.mapping(entry -> entry.getKey(), Collectors.toSet())));

I had to replace Map.Entry::getValue with entry -> (Set<String>) entry.getValue() and the other one too.

This helped me group the map by values and use them as keys. Thanks @nullpointer

In fact, this also works. The problem is I was not returning the right datatype.

Map<Set<String>, Set<String>> result = map.entrySet().parallelStream()
                .collect(
                Collectors.groupingBy(Map.Entry::getValue, 
                        Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM