我已经知道如何以艰难的方式完成它并使其工作 - 迭代条目并“手动”交换。但是我想知道,像这么多任务一样,这个问题能否以更优雅的方式解决。
我已阅读this post,遗憾的是它没有优雅的解决方案。我也没有可能使用任何花哨的Guava BiMaps或jdk之外的任何东西(已经定义了项目堆栈)。
我可以假设我的地图是双射的,顺便说一下:)
答案 0 :(得分:27)
Map<String, Integer> map = new HashMap<>();
Map<Integer, String> swapped = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
答案 1 :(得分:22)
如果您没有选择使用第三方库,我不认为以下代码如此丑陋(尽管某些脚本语言确实有优雅的方法):
//map must be a bijection in order for this to work properly
public static <K,V> HashMap<V,K> reverse(Map<K,V> map) {
HashMap<V,K> rev = new HashMap<V, K>();
for(Map.Entry<K,V> entry : map.entrySet())
rev.put(entry.getValue(), entry.getKey());
return rev;
}
答案 2 :(得分:9)
标准API / Java运行时不提供双向映射,因此唯一的解决方案是迭代所有条目并手动交换它们。
你可以做的是创建一个包装器类,它包含两个映射,并在内部执行双put()
,因此您可以快速获得两个数据视图。
[编辑]此外,由于开源,您不必包含第三方库,您只需将所需的类复制到您自己的项目中。
答案 3 :(得分:3)
地图不像列表,可以通过尾部交换来反转。
地图中的对象具有计算位置,并且使用值作为键,并且将键作为值来重新计算存储位置,从而构建另一个地图。没有优雅的方式。
然而,有双向地图。这些可能适合您的需求。我会重新考虑使用第三方库。
答案 4 :(得分:2)
有些工作可以简化到某一点,而不是更多。这可能就是其中之一!
如果你想使用Java集合apis来完成这项工作,那么蛮力就是要走的路 - 它会很快(除非集合很大)并且它将是一段显而易见的代码。
答案 5 :(得分:1)
作为回答的提示 https://stackoverflow.com/a/42091477/8594421
仅当地图不是HashMap并且不包含重复值时才有效。
Map<String,String> newMap = oldMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
抛出异常
java.lang.IllegalStateException:Duplicate key
如果有多个值。
解决方案:
HashMap<String,String> newMap = new HashMap<>();
for(Map.Entry<String,String> entry : oldMap.entrySet())
newMap.put(entry.getValue(), entry.getKey());
// Add inverse to old one
oldMap.putAll(newMap);
答案 6 :(得分:1)
如果您有权访问apache commons-collection,则可以使用MapUtils.invertMap。
注意:值重复的情况是不确定的。
(回复此,因为这是Google对“ java反向映射”的第一个结果)。
答案 7 :(得分:0)
这也适用于地图中的重复值,但不适用于HashMap
作为值。
package Sample;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Sample {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
Map<String, Set<String> > newmap = new HashMap<String, Set<String> >();
map.put("1", "a");
map.put("2", "a");
map.put("3", "b");
map.put("4", "b");
System.out.println("before Reversing \n"+map.toString());
for (Map.Entry<String, String> entry : map.entrySet())
{
String oldVal = entry.getValue();
String oldKey = entry.getKey();
Set<String> newVal = null;
if (newmap.containsKey(oldVal))
{
newVal = newmap.get(oldVal);
newVal.add(oldKey);
}
else
{
newVal= new HashSet<>();
newVal.add(oldKey);
}
newmap.put(oldVal, newVal);
}
System.out.println("After Reversing \n "+newmap.toString());
}
}
答案 8 :(得分:0)
Java 流 API 提供了一组很好的 API,可以帮助您解决这个问题。
如果值是唯一的,那么下面的方法会起作用。当我指的是值时,我指的是 Map
Map<String, Integer> map = new HashMap<>();
Map<Integer, String> swapped = map.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
如果值不是唯一的,则使用以下内容:
Map<Integer, List<String>> swapped = map.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
感谢 Nikita 和 FreyaZ。发布新答案,因为 Nikita 的答案有很多编辑队列