Java中的Map反转key和value

后端 潘老师 7个月前 (10-14) 637 ℃ (0) 扫码查看

这个Java教程将教我们如何使用不同的技术来反转给定的Map的key和value。我们将学习如何反转具有唯一值的Map,并在存在重复值时创建Multimap。

1.什么是反转的Map?

一个反转的Map <V, K> 是原始Map<K, V>的一个实例。原始Map的值成为结果Map的键,而原始Map的键成为值。

Map<String, String> map = Map.of("key1", "value1", "key2", "value2");
System.out.println(map);   //{key1=value1, key2=value2}

//反转后
{value1=key1, value2=key2}

2.反转具有唯一值的Map

以下方法应该用于反转包含唯一值的Map,因为我们没有使用任何机制来解决重复的键/值。

2.1. 使用for循环

反转Map的最简单方式是使用循环。我们遍历Map的条目并将它们添加到一个新的Map中。在添加条目时,我们互换键和值。

Map<Integer, String> invertedMap = new HashMap<>();

for (Map.Entry<String, Integer> entry : originalMap.entrySet()) {
  invertedMap.put(entry.getValue(), entry.getKey());
}

2.2. 使用Collectors.toMap()

Stream API提供了Collectors.toMap()来方便地将Stream元素收集到Map中。我们需要遍历Stream元素并按相反的顺序收集条目。

Map<Integer, String> inverseMap = originalMap.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));

3.反转具有重复值的Map

假设Map中有一些具有重复值的条目。现在,在反转Map时,我们必须决定如何处理这些值,因为反转后的Map不允许重复的键。

通常,在这些情况下创建一个MultiMap是正确的解决方案。MultiMap类似于一个Map,不同之处在于可以有相同的键对应多个元素。

3.1. 使用for循环

在下面的示例中,使用一个List来存储一个键的多个值,从而得到一个Multimap。

Map<Integer, String> mapWithDuplicateValues = new HashMap<Integer, String>();
mapWithDuplicateValues.put(1, "Value1");
mapWithDuplicateValues.put(2, "Value2");
mapWithDuplicateValues.put(3, "Value2");

HashMap<String, List<Integer>> inverseMap = new HashMap<String, List<Integer>>();

for (Map.Entry<Integer, String> entry : mapWithDuplicateValues.entrySet()) {
  if (inverseMap.containsKey(entry.getValue())) {
    inverseMap.get(entry.getValue()).add(entry.getKey());
  } else {
    List<Integer> list = new ArrayList<Integer>();
    list.add(entry.getKey());
    inverseMap.put(entry.getValue(), list);
  }
}
System.out.println(inverseMap);   //{Value1=[1], Value2=[2, 3]}

3.2. 使用Collectors.groupBy()

在下面的示例中,Collectors.mapping()函数通过传递给收集器的方式,对重复值执行归约操作,将重复值收集到一个List中。

HashMap<String, List<Integer>> inverseMap = originalMap.entrySet()
      .stream()
      .collect(Collectors.groupingBy(Entry::getValue,
              Collectors.mapping(Entry::getKey, Collectors.toList())));

4.使用Guava库

Guava是由Google创建的开源Java库。它提供了许多有用的集合和接口。我们将使用以下Map来反转给定的Map。

4.1. 使用Multimap

Multimap是一个直接的实现,内部管理重复的值。

Multimap<Integer, String> multimap = ImmutableMultimap.of(1, "Key1", 1, "Key2", 2, "Key3");

System.out.println(multimap); //{1=[Key1, Key2], 2=[Key3]}

4.2. 使用BiMap

BiMap是一个双向Map,维护了Map的反向视图,即键和值颠倒的条目。此Map还确保不会在Map中存储重复的值或键。

BiMap<Integer, String> biMap = ImmutableBiMap.of(1, "Key1", 2, "Key2", 3, "Key3");
BiMap<String, Integer> inverseBiMap = biMap.inverse();

System.out.println(inverseBiMap); //{Key1=1, Key2=2, Key3=3}

还有一个名为HashBiMap的类,它由两个哈希表支持,一个用于键到值的映射,另一个用于值到键的映射。这个实现允许空键和值。

BiMap<Integer,String> originalMap = HashBiMap.create();
//add key-value pairs

BiMap<String, Integer> inversedMap = biMap.inverse();

5.使用Apache Commons-Collections

Apache Commons Collections库提供了各种实现和工具,以便轻松处理集合。我们将使用BidiMap和inverseBidiMap()方法来反转Map,方法与Guava类似。

5.1. 使用BidiMap

BidiMap接口允许在键和值之间进行双向查找。以下是该接口的不同实现:

  • DualHashBidiMap:它使用两个HashMap实例,以提供使用键或值快速查找条目。
  • DualLinkedHashBidiMap:它使用两个LinkedHashMap实例,以牺牲存储两组链表和映射条目的代价来进行快速查找。
  • TreeBidiMap:这个Map基于红黑树实现,保证键-值将根据键和值的自然顺序以升序方式存储。
  • DualTreeBidiMap:它使用两个TreeMap实例,使其比TreeBidiMap更昂贵,因为它将每个对象存储两次。我们可以使用inverseBidiMap()方法获得原始Map的反向视图。请注意,当找到重复值时,后面的键将覆盖前面的键。
BidiMap bidiMap = new DualHashBidiMap();
bidiMap.put(1, "Value1");
bidiMap.put(2, "Value2");

System.out.println(bidiMap.inverseBidiMap());         //{Value1=1, Value2=2}

5.2. 使用MapUtils.invertMap()

invertMap()方法返回一个新的HashMap,其中键和值被交换。请注意,如果原始Map对多个键有重复的值,返回的Map将包含其中一个键,但应该映射的确切键将未定义。

Map<Integer, String> hashMap = new HashMap<Integer, String>();
hashMap.put(1,"Value1");
hashMap.put(2,"Value2");
hashMap.put(3,"Value2");

Map<String,Integer> inversedMap1 = MapUtils.invertMap(hashMap);
System.out.println(inversedMap1);  //{Value1=1, Value2=3}

6.结论

在这个Java教程中,我们学习了如何使用不同的技术反转给定的Map,从for循环到Guava和Apache Commons的方法。我们还学习了如何反转具有重复值的Map。反转给定的Map的有效方式是使用外部库,如Guava或Apache Commons,而不是遍历条目。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/9535.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】