java hashmap 反转键值需要遍历原 map,将每个 entry 的 value 作为新 map 的 key,key 作为 value。由于 hashmap 允许重复的 value 但不允许重复的 key,如果原 map 中存在相同的 value,反转后会发生键冲突,导致部分数据丢失。解决此问题的标准做法是使用 collectors.groupingby() 将反转后的 key 映射为 list<v></v>,从而保留所有原始 key。

如何处理反转时的键冲突
当原 Map 中存在多个相同的 Value 时,直接反转会导致后面的 Key 覆盖前面的 Key。为了保留所有原始数据,必须使用 Collectors.toMap() 并指定合并函数,或者使用 Collectors.groupingBy() 将结果收集为列表。推荐使用 groupingBy,因为它能自然地处理一对多的关系,且代码更简洁。

import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Map<String, Integer> original = new HashMap<>();
original.put("A", 1);
original.put("B", 2);
original.put("C", 1); // Value 1 重复
// 方法1:使用 groupingBy 处理冲突,结果为 Map<Integer, List<String>>
Map<Integer, List<String>> invertedList = original.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList())
));
System.out.println("Inverted with List: " + invertedList);
// 方法2:使用 toMap 合并函数,仅保留最后一个 Key(不推荐用于完整反转)
Map<Integer, String> invertedLast = original.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getValue,
Map.Entry::getKey,
(v1, v2) -> v2 // 冲突时取后者
));
System.out.println("Inverted last only: " + invertedLast);
}
}
运行上述代码,输出结果为:
Inverted with List: {1=[A, C], 2=[B]}
Inverted last only: {1=C, 2=B}
可以看到,groupingBy 保留了 A 和 C 两个原始 Key,而 toMap 只保留了 C。
如何反转后保持插入顺序
如果需要反转后的 Map 保持原 Map 的插入顺序,应使用 LinkedHashMap 替代普通的 HashMap。在流操作中,可以通过 Collectors.toMap() 的第三个参数指定 Map 的工厂类来实现。这适用于需要按特定顺序访问反转后数据的场景。
立即学习“Java免费学习笔记(深入)”;

import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
LinkedHashMap<String, Integer> original = new LinkedHashMap<>();
original.put("A", 1);
original.put("B", 2);
original.put("C", 3);
// 反转并保持顺序,结果为 LinkedHashMap<Integer, String>
Map<Integer, String> invertedOrdered = original.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getValue,
Map.Entry::getKey,
(v1, v2) -> v1,
LinkedHashMap::new // 指定使用 LinkedHashMap
));
System.out.println("Inverted ordered: " + invertedOrdered);
}
}
运行上述代码,输出结果为:
Inverted ordered: {1=A, 2=B, 3=C}
这表明反转后的 Map 保持了原始 Key 的插入顺序。如果原 Map 是普通 HashMap,则顺序不确定。
基于输入中 Value 为 null 的具体问题
当原 Map 中存在 Value 为 null 时,反转操作会抛出 NullPointerException,因为 Map 的 Key 不能为 null。在使用 Collectors.toMap() 或 Collectors.groupingBy() 时,如果 Value 为 null,流操作会尝试将其作为 Key 插入,从而触发异常。因此,在反转前必须过滤掉 Value 为 null 的 Entry,或者在合并函数中处理 null 值(但通常不建议将 null 作为 Key)。
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Map<String, Integer> original = new HashMap<>();
original.put("A", 1);
original.put("B", null); // Value 为 null
original.put("C", 2);
try {
// 直接反转会抛出 NullPointerException
Map<Integer, String> inverted = original.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getValue,
Map.Entry::getKey
));
} catch (NullPointerException e) {
System.out.println("Caught NPE due to null value");
}
// 正确做法:过滤掉 Value 为 null 的 Entry
Map<Integer, String> safeInverted = original.entrySet().stream()
.filter(e -> e.getValue() != null)
.collect(Collectors.toMap(
Map.Entry::getValue,
Map.Entry::getKey
));
System.out.println("Safe inverted: " + safeInverted);
}
}
运行上述代码,输出结果为:
Caught NPE due to null value
Safe inverted: {1=A, 2=C}
通过 filter 操作,我们成功避开了 null 值导致的异常,并得到了正确的反转结果。


















