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


当前回答

设值为maxValue。

Set keySet = map.keySet();

keySet.stream().filter(x->map.get(x)==maxValue).forEach(x-> System.out.println(x));

其他回答

用你自己的实现来装饰地图

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);
    }
}
for(int key: hm.keySet()) {
    if(hm.get(key).equals(value)) {
        System.out.println(key); 
    }
}

据我所知,当你将HashMap的键和值表示为数组时,它们是不混合的:

hashmap.values().toArray()

and

hashmap.keySet().toArray()

所以下面的代码(从java 8开始)应该像预期的那样工作:

public Object getKeyByFirstValue(Object value) {
    int keyNumber =  Arrays.asList(hashmap.values().toArray()).indexOf(value);
    return hashmap.keySet().toArray()[keyNumber];
}

然而,(警告!)它的工作速度比迭代慢2-3倍。

如果你的数据结构在键和值之间有多对一映射,你应该遍历条目并选择所有合适的键:

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

此外,对于番石榴用户来说,BiMap可能也很有用。例如:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);

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

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

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

Map<Value, Set<Key>>

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