如何反转地图

问题描述 投票:0回答:2

我们来一张地图:

  • A -> {1, 2, 3}
  • B -> {3, 4, 5}
  • C -> {2, 3, 5}

我需要反转这张地图并获得:

  • 1 -> {A}
  • 2 -> {A,C}
  • 3 -> {A、B、C}
  • 4 -> {B}
  • 5 -> {B,C}

我成功地用这段代码做到了:

public static <U, V> Map<V, Set<U>> reverseMap(Map<U, Set<V>> map) {
  Map<V, Set<U>> result = Maps.newHashMap();
  for(Map.Entry<U, Set<V>> entry : map.entrySet()) {
    for(V value : entry.getValue()) {

      Set<U> set = result.get(value);
      if(set == null) {
        set = Sets.newHashSet();
        result.put(value, set);
      }
      set.add(entry.getKey());
      result.put(value, set);
    }

  }
  return result;
}

但这只是反向索引,所以我认为可能存在一个预定义的方法来执行此操作。

有人知道这样的图书馆吗? Guava 中的方法?

java guava
2个回答
7
投票

如果您将

HashMap<U, Set<V>>
替换为
HashMultimap<U, V>
(它们是等效的,并且
Multimap
更易于使用),您现在可以使用
Multimaps.invertFrom()
,它将填充
Multimap<V, U>


请注意,正如 Javadoc 中提到的,如果您使用

ImmutableMultimap
,则可以直接调用
ImmutableMultimap.inverse()


0
投票

这是 Java 8+ 中使用流的解决方案:

Map<V, Set<U>> invertedMap = map.entrySet().stream()
        .flatMap(e -> e.getValue().stream()
                .map(v -> Map.entry(e.getKey(), v)))
        .collect(Collectors.groupingBy(
                Map.Entry::getValue,
                Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));

逐步分解

  1. 将地图转换为条目流
    // Stream<Map.Entry<U, Set<V>>>
    map.entrySet().stream()
    
  2. 将值列表中的每个条目拆分为单独的项目
    // Stream<Map.Entry<U, V>>
    .flatMap(e -> e.getValue().stream().map(v -> Map.entry(e.getKey(), v)))
    
  3. 将条目分组到一个新映射中,其中键等于先前的值,并且值包含映射到该值的每个原始键的列表。
    // Map<V, Set<U>>
    .collect(Collectors.groupingBy(
            Map.Entry::getValue,
            Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));
    
© www.soinside.com 2019 - 2024. All rights reserved.