拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何在Java 中反转Map

如何在Java 中反转Map

白鹭 - 2022-03-07 2340 0 2

一、概述

在这篇快速文章中,我们将了解如何在Java 中反转Map这个想法是为Map<K, V>类型的给定地图创建Map<V, K>的新实例。此外,我们还将了解如何处理源映射中存在重复值的情况。

请参阅我们的另一篇文章以了解有关HashMap类本身的更多信息。

2. 定义问题

假设我们有一个包含几个Key-Value对的Map

Map<String, Integer> map = new HashMap<>();
 map.put("first", 1);
 map.put("second", 2);

原始Map将存储以下项目:

{first=1, second=2}

相反,我们希望将键转换为值,反之亦然,转换为新的Map对象。结果将是:

{1=first, 2=second}

3. 使用传统for循环

首先,让我们看看如何使用for循环反转Map

public static <V, K> Map<V, K> invertMapUsingForLoop(Map<K, V> map) {
 Map<V, K> inversedMap = new HashMap<V, K>();
 for (Entry<K, V> entry : map.entrySet()) {
 inversedMap.put(entry.getValue(), entry.getKey());
 }
 return inversedMap;
 }

在这里,我们正在遍历Map对象的entrySet()之后,我们将原来的Value作为新的Key,将原来的Key作为新的Value添加到inversedMap对像.换句话说,我们通过用值替换键和用键替换值来复制映射的内容此外,这适用于8 之前的Java 版本,但我们应该注意,这种方法仅在源映射的值是唯一的情况下才有效

4. 使用StreamAPI 反转Map

Java 8 提供了来自StreamAPI 的便捷方法,以更实用的风格反转Map让我们来看看其中的几个。

4.1.Collectors.groupingBy()

有时,即使源映射包含重复值,我们也可能需要所有键。或者,Collectors.groupingBy()为处理重复值提供了更好的控制

例如,假设我们有以下Key Value

{first=1, second=2, two=2}

这里,值“2”针对不同的键重复两次。在这些情况下,我们可以使用groupingBy()方法在Value对像上实现级联的“分组依据”操作:

private static <V, K> Map<V, List<K>> invertMapUsingGroupingBy(Map<K, V> map) {
 Map<V, List<K>> inversedMap = map.entrySet()
 .stream()
 .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
 return inversedMap;
 }

稍微解释一下,Collectors.mapping()函数使用指定的收集器对与给定键关联的值执行归约操作。groupingBy()收集器将重复值收集到List中,从而产生MultiMap现在的输出将是:

{1=[first], 2=[two, second]}

4.2**Collectors.toMap()**

如果源映射中没有任何重复值,我们可以使用Collectors.toMap()

public static <V, K> Map<V, K> invertMapUsingStreams(Map<K, V> map) {
 Map<V, K> inversedMap = map.entrySet()
 .stream()
 .collect(Collectors.toMap(Entry::getValue, Entry::getKey));
 return inversedMap;
 }

首先,entrySet()被转换为对象流。随后,我们使用Collectors.toMap()KeyValue收集到inversedMap对像.

让我们考虑源映射包含重复值。在这种情况下,我们可以使用映射函数将自定义规则应用于输入元素

public static <K, V> Map<V, K> invertMapUsingMapper(Map<K, V> sourceMap) {
 return sourceMap.entrySet()
 .stream().collect(
 Collectors.toMap(Entry::getValue, Entry::getKey, (oldValue, newValue) -> oldValue)
 );
 }

在这个方法中,Collectors.toMap()的最后一个参数是一个映射函数。使用这个,我们可以自定义应该添加哪个键,以防有重复在上面的示例中,如果源映射包含重复值,我们将保留第一个值作为键。但是,如果值重复,我们只能保留一个键。


标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *