Java HashMap:如何从价值中获得钥匙?
如果我有值"foo"
,并且ftw.containsValue("foo")
返回true
的HashMap<String> ftw
,我怎么能得到相应的键? 我必须通过哈希映射循环? 什么是最好的方法来做到这一点?
如果您select使用Commons Collections库而不是标准Java Collections API,则可以轻松实现此目的。
集合库中的BidiMap接口是双向映射,允许您将键映射到值(如法线贴图),也可以将值映射到键,从而允许您在两个方向上执行查找。 getKey()方法支持获取值的键。
但有一点需要注意,双向映射不能有多个映射到键的值,因此除非您的数据集在键和值之间具有1:1映射,否则不能使用bidimaps。
更新
如果您想依赖Java Collections API,则在将值插入到映射中时,必须确保键和值之间的1:1关系。 说起来容易做起来难。
一旦可以确保,使用entrySet()方法获取Map中的一组条目(映射)。 一旦获得了types为Map.Entry的集合,遍历这些条目,将存储的值与预期值进行比较,并获得相应的键值 。
更新#2
在Google Guava和重构的Commons-Collections库(后者不是Apache项目)中可以find对generics地图的支持。 感谢Esko指出Apache Commons Collections中缺less的通用支持。 使用具有generics的集合可以实现更多可维护的代码。
如果您的数据结构在键和值之间具有多对一的映射关系,您应该遍历条目并select所有合适的键:
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) { Set<T> keys = new HashSet<T>(); for (Entry<T, E> entry : map.entrySet()) { if (Objects.equals(value, entry.getValue())) { keys.add(entry.getKey()); } } return keys; }
如果是一对一关系,则可以返回第一个匹配的键:
public static <T, E> T getKeyByValue(Map<T, E> map, E value) { for (Entry<T, E> entry : map.entrySet()) { if (Objects.equals(value, entry.getValue())) { return entry.getKey(); } } return null; }
在Java 8中:
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) { return map.entrySet() .stream() .filter(entry -> Objects.equals(entry.getValue(), value)) .map(Map.Entry::getKey) .collect(Collectors.toSet()); }
此外,对于Guava用户, BiMap可能会有用。 例如:
BiMap<Token, Character> tokenToChar = ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '('); Token token = tokenToChar.inverse().get('('); Character c = tokenToChar.get(token);
public class NewClass1 { public static void main(String[] args) { Map<Integer, String> testMap = new HashMap<Integer, String>(); testMap.put(10, "a"); testMap.put(20, "b"); testMap.put(30, "c"); testMap.put(40, "d"); for (Entry<Integer, String> entry : testMap.entrySet()) { if (entry.getValue().equals("c")) { System.out.println(entry.getKey()); } } } }
一些额外的信息…可能对你有用
上面的方法可能不是很好,如果你的hashmap真的很大。 如果你的散列表包含唯一键映射的唯一键,你可以维护一个包含从值到键映射的散列表。
那就是你必须保持两个hashmaps
1. Key to value 2. Value to key
在这种情况下,你可以使用第二个hashmap来获得密钥。
你可以在你的地图结构中插入关键字,值对和它的逆
map.put("theKey", "theValue"); map.put("theValue", "theKey");
使用map.get(“theValue”)将返回“theKey”。
这是一个快速和肮脏的方式,我已经制作了不变的地图,这将只适用于less数几个数据集:
- 只包含1对1对
- 值的集合是从一组键(1-> 2,2-> 3中断它)是不相交的
我想你的select是
- 使用为此构build的地图实现,例如Google集合中的BiMap 。 请注意,谷歌collectionsBiMap需要无数值和密钥,但它提供了双向性能的高性能
- 手动维护两个地图 – 一个用于键 – >值,另一个地图用于值 – >键
- 通过
entrySet()
迭代并查找与值匹配的键。 这是最慢的方法,因为它需要遍历整个集合,而另外两个方法则不需要。
要查找映射到该值的所有键,请使用map.entrySet()
遍历散列映射中的所有对。
没有明确的答案,因为多个键可映射到相同的值。 如果使用自己的代码来强制实现唯一性,最好的解决scheme是创build一个使用两个HashMap来跟踪两个方向上的映射的类。
用你自己的实现装饰地图
class MyMap<K,V> extends HashMap<K, V>{ Map<V,K> reverseMap = new HashMap<V,K>(); @Override public V put(K key, V value) { // TODO Auto-generated method stub reverseMap.put(value, key); return super.put(key, value); } public K getKey(V value){ return reverseMap.get(value); } }
我认为这是最好的解决scheme,原始地址: Java2s
import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] argv) { Map<String, String> map = new HashMap<String, String>(); map.put("1","one"); map.put("2","two"); map.put("3","three"); map.put("4","four"); System.out.println(getKeyFromValue(map,"three")); } // hm is the map you are trying to get value from it public static Object getKeyFromValue(Map hm, Object value) { for (Object o : hm.keySet()) { if (hm.get(o).equals(value)) { return o; } } return null; } }
一个简单的用法:如果你把所有的数据都放在hasMap中,并且你有item =“Automobile”,所以你正在看hashMap中的key。 这是很好的解决scheme。
getKeyFromValue(hashMap, item); System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
恐怕你只需要迭代你的地图。 最短我能想出:
Iterator<Map.Entry<String,String>> iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String,String> entry = iter.next(); if (entry.getValue().equals(value_you_look_for)) { String key_you_look_for = entry.getKey(); } }
这听起来像是最好的方法是使用map.entrySet()
迭代条目,因为map.containsValue()
可能map.containsValue()
。
如果您在自己的代码中构build地图,请尝试将键和值放在一起:
public class KeyValue { public Object key; public Object value; public KeyValue(Object key, Object value) { ... } } map.put(key, new KeyValue(key, value));
那么当你有价值时,你也有钥匙。
for(int key: hm.keySet()) { if(hm.get(key).equals(value)) { System.out.println(key); } }
使用Java 8:
ftw.forEach((key, value) -> { if (value=="foo") { System.out.print(key); } });
对于针对API <19的Android开发,Vitalii Fedorenko一对一关系解决scheme不起作用,因为Objects.equals
未实现。 这是一个简单的select:
public <K, V> K getKeyByValue(Map<K, V> map, V value) { for (Map.Entry<K, V> entry : map.entrySet()) { if (value.equals(entry.getValue())) { return entry.getKey(); } } return null; }
您可以使用以下代码使用值获取密钥..
ArrayList valuesList = new ArrayList(); Set keySet = initalMap.keySet(); ArrayList keyList = new ArrayList(keySet); for(int i = 0 ; i < keyList.size() ; i++ ) { valuesList.add(initalMap.get(keyList.get(i))); } Collections.sort(valuesList); Map finalMap = new TreeMap(); for(int i = 0 ; i < valuesList.size() ; i++ ) { String value = (String) valuesList.get(i); for( int j = 0 ; j < keyList.size() ; j++ ) { if(initalMap.get(keyList.get(j)).equals(value)) { finalMap.put(keyList.get(j),value); } } } System.out.println("fianl map ----------------------> " + finalMap);
public static class SmartHashMap <T1 extends Object, T2 extends Object> { public HashMap<T1, T2> keyValue; public HashMap<T2, T1> valueKey; public SmartHashMap(){ this.keyValue = new HashMap<T1, T2>(); this.valueKey = new HashMap<T2, T1>(); } public void add(T1 key, T2 value){ this.keyValue.put(key, value); this.valueKey.put(value, key); } public T2 getValue(T1 key){ return this.keyValue.get(key); } public T1 getKey(T2 value){ return this.valueKey.get(value); } }
你可以使用下面的:
public class HashmapKeyExist { public static void main(String[] args) { HashMap<String, String> hmap = new HashMap<String, String>(); hmap.put("1", "Bala"); hmap.put("2", "Test"); Boolean cantain = hmap.containsValue("Bala"); if(hmap.containsKey("2") && hmap.containsValue("Test")) { System.out.println("Yes"); } if(cantain == true) { System.out.println("Yes"); } Set setkeys = hmap.keySet(); Iterator it = setkeys.iterator(); while(it.hasNext()) { String key = (String) it.next(); if (hmap.get(key).equals("Bala")) { System.out.println(key); } } } }
public static String getKey(Map<String, Integer> mapref, String value) { String key = ""; for (Map.Entry<String, Integer> map : mapref.entrySet()) { if (map.getValue().toString().equals(value)) { key = map.getKey(); } } return key; }
是的,你必须通过hashmap循环,除非你按照这些不同的答案build议的东西来实现。 而不是摆弄entrySet,我只是得到keySet(),迭代该集合,并保持(第一个)键,让你的匹配值。 如果你需要所有与这个值相匹配的密钥,显然你必须完成整个事情。
正如Jonas所指出的那样,这可能已经是containsValue方法的作用了,所以你可以直接跳过这个testing,每次只做一次迭代(或者编译器已经消除冗余,谁知道呢)。
另外,相对于其他答案,如果你的反向地图看起来像
Map<Value, Set<Key>>
你可以处理非唯一键 – >值映射,如果你需要这个function(把它们解开)。 这将纳入任何人们在这里使用两个地图build议的解决scheme。
import java.util.HashMap; import java.util.HashSet; import java.util.Set; public class ValueKeysMap<K, V> extends HashMap <K,V>{ HashMap<V, Set<K>> ValueKeysMap = new HashMap<V, Set<K>>(); @Override public boolean containsValue(Object value) { return ValueKeysMap.containsKey(value); } @Override public V put(K key, V value) { if (containsValue(value)) { Set<K> keys = ValueKeysMap.get(value); keys.add(key); } else { Set<K> keys = new HashSet<K>(); keys.add(key); ValueKeysMap.put(value, keys); } return super.put(key, value); } @Override public V remove(Object key) { V value = super.remove(key); Set<K> keys = ValueKeysMap.get(value); keys.remove(key); if(keys.size() == 0) { ValueKeysMap.remove(value); } return value; } public Set<K> getKeys4ThisValue(V value){ Set<K> keys = ValueKeysMap.get(value); return keys; } public boolean valueContainsThisKey(K key, V value){ if (containsValue(value)) { Set<K> keys = ValueKeysMap.get(value); return keys.contains(key); } return false; } /* * Take care of argument constructor and other api's like putAll */ }
/** * This method gets the Key for the given Value * @param paramName * @return */ private String getKeyForValueFromMap(String paramName) { String keyForValue = null; if(paramName!=null)) { Set<Entry<String,String>> entrySet = myMap().entrySet(); if(entrySet!=null && entrySet.size>0) { for(Entry<String,String> entry : entrySet) { if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) { keyForValue = entry.getKey(); } } } } return keyForValue; }
import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; public class M{ public static void main(String[] args) { HashMap<String, List<String>> resultHashMap = new HashMap<String, List<String>>(); Set<String> newKeyList = resultHashMap.keySet(); for (Iterator<String> iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) { String hashKey = (String) iterator.next(); if (!newKeyList.contains(originalHashMap.get(hashKey))) { List<String> loArrayList = new ArrayList<String>(); loArrayList.add(hashKey); resultHashMap.put(originalHashMap.get(hashKey), loArrayList); } else { List<String> loArrayList = resultHashMap.get(originalHashMap .get(hashKey)); loArrayList.add(hashKey); resultHashMap.put(originalHashMap.get(hashKey), loArrayList); } } System.out.println("Original HashMap : " + originalHashMap); System.out.println("Result HashMap : " + resultHashMap); } }
使用薄包装: HMap
import java.util.Collections; import java.util.HashMap; import java.util.Map; public class HMap<K, V> { private final Map<K, Map<K, V>> map; public HMap() { map = new HashMap<K, Map<K, V>>(); } public HMap(final int initialCapacity) { map = new HashMap<K, Map<K, V>>(initialCapacity); } public boolean containsKey(final Object key) { return map.containsKey(key); } public V get(final Object key) { final Map<K, V> entry = map.get(key); if (entry != null) return entry.values().iterator().next(); return null; } public K getKey(final Object key) { final Map<K, V> entry = map.get(key); if (entry != null) return entry.keySet().iterator().next(); return null; } public V put(final K key, final V value) { final Map<K, V> entry = map .put(key, Collections.singletonMap(key, value)); if (entry != null) return entry.values().iterator().next(); return null; } }
我的2美分。 你可以得到一个数组中的键,然后遍历数组。 这会影响这个代码块的性能,如果地图非常大的话,那么你首先得到一个数组中的键,这可能会消耗一些时间,然后循环。 否则,小地图应该没问题。
String[] keys = yourMap.keySet().toArray(new String[0]); for(int i = 0 ; i < keys.length ; i++){ //This is your key String key = keys[i]; //This is your value yourMap.get(key) }
在java8中
map.entrySet().stream().filter(entry -> entry.getValue().equals(value)) .forEach(entry -> System.out.println(entry.getKey()));
重要的是要注意,由于这个问题,Apache集合支持genericsBidiMaps 。 所以在这一点上,一些顶尖的投票答案就不再准确了。
对于也支持重复值的序列化BidiMap(一对多场景),也可以考虑MapDB.org 。
-
如果你想从价值中获得钥匙,最好使用bidimap(双向地图),你可以从O(1)时间的价值中获得钥匙。
但是,这个缺点是你只能使用唯一的键集和值集。
-
在java中有一个名为Table的数据结构,它不过是像地图一样的地图
表<A,B,C> ==地图<A,地图<B,C>>
在这里你可以通过查询
T.row(a);
得到map<B,C>
T.row(a);
,也可以通过查询T.column(b);
得到map<A,C>
T.column(b);
在你的特殊情况下,插入C作为一些常数。
所以它就像<a1,b1,1> <a2,b2,1>,…
所以,如果你通过T.row(a1)find—>返回地图 – > get keyset这个返回的地图。
如果您需要查找关键值,那么T.column(b2) – >返回地图 – >获取返回地图的keyset。
与以前的案例相比的优势:
- 可以使用多个值。
- 使用大型数据集时效率更高。
我认为keySet()可能很好地find映射到值的键,并且比entrySet()具有更好的编码风格。
例如:
假设你有一个HashMap 映射 ,ArrayList res ,一个你想要查找所有映射关键字的值 ,然后将关键字存储到res中 。
你可以在下面写下代码:
for (int key : map.keySet()) { if (map.get(key) == value) { res.add(key); } }
而不是使用下面的entrySet():
for (Map.Entry s : map.entrySet()) { if ((int)s.getValue() == value) { res.add((int)s.getKey()); } }
希望能帮助到你 :)
Iterator<Map.Entry<String,String>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String,String> entry = iterator.next(); if (entry.getValue().equals(value_you_look_for)) { String key_you_look_for = entry.getKey(); } }