如果我有值“foo”,和一个HashMap<String> ftw,其中ftw. containsvalue(“foo”)返回真,我怎么能得到相应的键?我需要遍历hashmap吗?最好的方法是什么?


当前回答

我认为keySet()可以很好地找到映射到值的键,并且具有比entrySet()更好的编码风格。

Ex:

假设你有一个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());
        }
    }

希望能有所帮助。

其他回答

需要注意的是,由于这个问题,Apache Collections支持通用的BidiMaps。因此,一些投票最多的答案在这一点上不再准确。

对于支持重复值(一对多场景)的Serialized BidiMap,也可以考虑MapDB.org。

是的,您必须遍历hashmap,除非您按照这些不同答案所建议的方式实现某些东西。而不是摆弄entrySet,我只获得keySet(),遍历该集合,并保留为您提供匹配值的(第一个)键。如果你需要所有匹配这个值的键,显然你需要做所有的事情。

正如Jonas所建议的,这可能已经是containsValue方法正在做的事情,所以您可以完全跳过这个测试,而只是每次都进行迭代(或者编译器可能已经消除了冗余,谁知道呢)。

另外,相对于其他答案,如果你的反向映射看起来像

Map<Value, Set<Key>>

如果需要这种功能,您可以处理非唯一key->值映射(先解开它们)。这将把fine纳入人们建议的任何解决方案中,使用两张地图。

你可以使用下面的代码获取键值。

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);
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
     */
}
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();
}
}