Reverse HashMap keys and values in Java
这是一个简单的问题,
我有一个简单的HashMap,我想反转其键和值。
1 2 3
| HashMap <Character, String > myHashMap = new HashMap <Character, String >();
myHashMap. put('a', "test one");
myHashMap. put('b', "test two"); |
我想创建一个新的HashMap,在其中放置相反的内容。
1 2
| HashMap <String, Character > reversedHashMap = new HashMap <String, Character >();
e. g. Keys"test one" &"test two" and values 'a' & 'b'. |
-
简单的问题,简单的答案。 你能告诉我们你卡在哪里吗?
-
首先,您必须确保自己的价值观是唯一的。 否则,它应该是Map>
-
好吧,我对JAVA相当陌生,不知道从哪里开始...
-
它们都是独一无二的,是的
-
这并不总是可能不丢失数据。 想象一下,您有一个:->测试一个; b->测试两个; c->测试一个(在您的第一个地图中)。 您将在第二张(输出)地图中得到什么? 像这样:测试一个-> a(或c); 测试两个-> b。 所以第一张地图有3个条目,第二张地图只有2个条目。
They all are unique, yes
如果您确定自己的值是唯一的,则可以遍历旧地图的条目。
1 2 3 4
| Map <String, Character > myNewHashMap = new HashMap <>();
for(Map. Entry<Character, String > entry : myHashMap. entrySet()){
myNewHashMap. put(entry. getValue(), entry. getKey());
} |
另外,您可以使用Guava提供的双向地图,并使用inverse()方法:
1 2 3 4 5
| BiMap <Character, String > myBiMap = HashBiMap. create();
myBiMap. put('a', "test one");
myBiMap. put('b', "test two");
BiMap <String, Character > myBiMapInversed = myBiMap. inverse(); |
随着java-8的发布,您也可以通过以下方式进行操作:
1 2 3 4 5 6 7 8
| Map <String, Integer > map = new HashMap <>();
map. put("a", 1);
map. put("b", 2);
Map <Integer, String > mapInversed =
map. entrySet()
. stream()
. collect(Collectors. toMap(Map.Entry::getValue, Map.Entry::getKey )) |
最后,我对质子包装库做出了贡献,该库包含Stream API的实用程序方法。这样,您可以这样做:
1
| Map <Character, String > mapInversed = MapStream. of(map ). inverseMapping(). collect(); |
-
感谢您解释双向地图的用法。 我不知道,这对我真的有用!
-
当我将Java-8方法与收集器一起使用时,在Map.Entry::getValue和getKey上出现以下错误:Non-static method cannot be referenced from a static context
-
一月,这是因为您的地图与使用mapInversed变量声明的泛型类型不同。
-
如果值重复怎么办? 你如何处理?
-
@ChaitanyaUttarwar您必须找到一种合并策略,以映射与原始映射中与同一值相关联的不同键(您可以将它们分组为列表,将它们求和,仅取一个键取决于您要实现的目标)。
Apache Commons Collections库提供了一种用于反转地图的实用方法。如果您确定myHashMap的值是唯一的,则可以使用此方法
1
| org. apache. commons. collections. MapUtils. invertMap(java. util. Map map ) |
样例代码
1
| HashMap <String, Character > reversedHashMap = MapUtils. invertMap(myHashMap ) |
如果值不是唯一的,则逆映射的安全方法是使用Java 8的groupingBy函数
1 2 3 4 5 6 7 8
| Map <String, Integer > map = new HashMap <>();
map. put("a", 1);
map. put("b", 2);
Map <Integer, List <String >> mapInversed =
map. entrySet()
. stream()
. collect(Collectors. groupingBy(Map.Entry::getValue, Collectors. mapping(Map.Entry::getKey, Collectors. toList()))) |
我写了一个更简单的循环,也可以工作(请注意,我所有的值都是唯一的):
1 2 3 4 5 6
| HashMap <Character, String > myHashMap = new HashMap <Character, String >();
HashMap <String, Character > reversedHashMap = new HashMap <String, Character >();
for (char i : myHashMap. keySet()) {
reversedHashMap. put(myHashMap. get(i ), i );
} |
1 2 3 4 5 6 7
| private <A, B > Map <B, A > invertMap (Map <A, B > map ) {
Map <B, A > reverseMap = new HashMap <>();
for (Map. Entry<A, B > entry : map. entrySet()) {
reverseMap. put(entry. getValue(), entry. getKey());
}
return reverseMap ;
} |
重要的是要记住,put在用相同的键调用时会替换该值。因此,如果您的地图具有两个具有相同值的键,则倒置地图中将只存在其中一个。
-
我认为有关如何处理重复值成为键的注释会很有用。
-
@CHBuckingham同意
要回答有关如何执行此操作的问题,可以从地图中获取entrySet,然后通过将getValue用作key并将getKey用作value来放入新地图。
但是请记住,映射中的键是唯一的,这意味着,如果您的原始映射中有一个值带有两个不同的键,则只有第二个键(按迭代顺序)将作为新映射中的值保留。
遍历键和值的列表,然后添加它们。
1 2 3 4
| HashMap <String, Character > reversedHashMap = new HashMap <String, Character >();
for (String key : myHashMap. keySet()){
reversedHashMap. put(myHashMap. get(key ), key );
} |
-
entrySet更好,不必在每个get上计算哈希码
-
@ A4L没错,但是对于简单的任务并没有太大的区别。
在下面的示例代码段中进行了测试,并在MapUtils和Java8 Stream功能中进行了尝试。它适用于两种情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public static void main (String[] args ) {
Map <String, String > test = new HashMap <String, String >();
test. put("a", "1");
test. put("d", "1");
test. put("b", "2");
test. put("c", "3");
test. put("d", "4");
test. put("d", "41");
System. out. println(test );
Map <String, String > test1 = MapUtils. invertMap(test );
System. out. println(test1 );
Map <String, String > mapInversed =
test. entrySet()
. stream()
. collect(Collectors. toMap(Map.Entry::getValue, Map.Entry::getKey ));
System. out. println(mapInversed );
}
Output :
{a =1, b =2, c =3, d =41}
{1=a, 2=b, 3=c, 41=d }
{1=a, 2=b, 3=c, 41=d } |