Java反转映射

我需要创建逆映射 – 选择唯一值并为它们找到键。 似乎只有迭代所有键/​​值对的方法,因为entrySet返回的set值不是唯一的? 谢谢。

地图中的值可能不是唯一的。 但是如果它们(在你的情况下)你可以按照你在问题中写的那样做,并创建一个通用方法来转换它:

private static  Map invert(Map map) { Map inv = new HashMap(); for (Entry entry : map.entrySet()) inv.put(entry.getValue(), entry.getKey()); return inv; } 

Java 8:

 public static  Map invert(Map map) { return map.entrySet() .stream() .collect(Collectors.toMap(Entry::getValue, c -> c.getKey())); } 

用法示例:

 public static void main(String[] args) { Map map = new HashMap(); map.put("Hello", 0); map.put("World!", 1); Map inv = invert(map); System.out.println(inv); // outputs something like "{0=Hello, 1=World!}" } 

旁注: put(.., ..)方法将返回键的“旧”值。 如果它不为null,则可能抛出new IllegalArgumentException("Map values must be unique")或类似的东西。

看看Google Guava BiMap 。

用法示例

 Map map = new HashMap<>(); map.put(1, "one"); map.put(2, "two"); Map inverted = HashBiMap.create(map).inverse(); 

要在java 8中获取给定映射的反转forms:

 public static  Map inverseMap(Map sourceMap) { return sourceMap.entrySet().stream().collect( Collectors.toMap(Entry::getValue, Entry::getKey, (a, b) -> a) //if sourceMap has duplicate values, keep only first ); } 

用法示例

 Map map = new HashMap(); map.put(1, "one"); map.put(2, "two"); Map inverted = inverseMap(map); 

似乎只有迭代所有键/​​值对的方法,因为entrySet返回的set值不是唯一的?

这至少是一种方式。 这是一个例子:

 Map map = new HashMap(); map.put(1, "one"); map.put(2, "two"); Map inverted = new HashMap(); for (Integer i : map.keySet()) inverted.put(map.get(i), i); 

如果是非唯一值,则此算法会将找到的最后一个值映射到其密钥。 (由于大多数地图的迭代顺序未定义,因此这应该与任何解决方案一样好。)

如果您确实希望保留为每个键找到的第一个值,则可以将其更改为

 if (!inverted.containsKey(map.get(i))) inverted.put(map.get(i), i); 

Apache Commons Collections还为双向映射提供了BidiMap接口,以及多个实现。

BidiMap JavaDoc

我会给出另一个方法来给出一个额外的维度:EntrySet中的重复值

 public static void main(String[] args) { HashMap s = new HashMap(); s.put(1, "Value1"); s.put(2, "Value2"); s.put(3, "Value2"); s.put(4, "Value1"); /* * swap goes here */ HashMap> newMap = new HashMap>(); for (Map.Entry en : s.entrySet()) { System.out.println(en.getKey() + " " + en.getValue()); if(newMap.containsKey(en.getValue())){ newMap.get(en.getValue()).add(en.getKey()); } else { List tmpList = new ArrayList(); tmpList.add(en.getKey()); newMap.put(en.getValue(), tmpList); } } for(Map.Entry> entry: newMap.entrySet()){ System.out.println(entry.getKey() + " " + entry.getValue()); } } 

结果将是:

1 Value1
2 Value2
3 Value2
4 Value1
价值1 [1,4]
价值2 [2,3]

您必须假设值可能相同,因为Map合约允许它。

在我看来,最好的解决方案在于使用包装器。 它将包含原始值,并添加一个id。 它的hashCode()函数将依赖于id,并为原始值提供Getter。 代码将是这样的:

 public class MapKey { /** * A new ID to differentiate equal values */ private int _id; /** * The original value now used as key */ private String _originalValue; public MapKey(String originalValue) { _originalValue = originalValue; //assuming some method for generating ids... _id = getNextId(); } public String getOriginalValue() { return _originalValue; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _id; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; MapKey other = (MapKey) obj; if (_id != other._id) return false; return true; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("MapKey value is "); sb.append(_originalValue); sb.append(" with ID number "); sb.append(_id); return sb.toString(); } 

反转地图将是这样的:

 public Map  invertMap(Map  map) { Map  invertedMap = new HashMap (); Iterator> it = map.entrySet().iterator(); while(it.hasNext()) { //getting the old values (to be reversed) Entry entry = it.next(); Integer oldKey = entry.getKey(); String oldValue = entry.getValue(); //creating the new MapKey MapKey newMapKey = new MapKey(oldValue); invertedMap.put(newMapKey, oldKey); } return invertedMap; } 

打印这样的值:

 for(MapKey key : invertedMap.keySet()) { System.out.println(key.toString() + " has a new value of " + invertedMap.get(key)); } 

这些代码都没有经过测试,但我认为它是最好的解决方案,因为它使用OOinheritance设计而不是“c”样式检查,并允许您显示所有原始键和值。

与番石榴

 Multimaps.transformValues(Multimaps.index(map.entrySet(), Map.Entry::getValue), Map.Entry::getKey) 

你会得到一个multimap(基本上是一个列表的映射)作为回报。

Interesting Posts