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


当前回答

虽然这并没有直接回答问题,但它是相关的。

这样你就不需要继续创建/迭代了。只需创建一个反向映射一次,就可以得到你需要的东西。

/**
 * Both key and value types must define equals() and hashCode() for this to work.
 * This takes into account that all keys are unique but all values may not be.
 *
 * @param map
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<V, List<K>> reverseMap(Map<K,V> map) {
    if(map == null) return null;

    Map<V, List<K>> reverseMap = new ArrayMap<>();

    for(Map.Entry<K,V> entry : map.entrySet()) {
        appendValueToMapList(reverseMap, entry.getValue(), entry.getKey());
    }

    return reverseMap;
}


/**
 * Takes into account that the list may already have values.
 * 
 * @param map
 * @param key
 * @param value
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<K, List<V>> appendValueToMapList(Map<K, List<V>> map, K key, V value) {
    if(map == null || key == null || value == null) return map;

    List<V> list = map.get(key);

    if(list == null) {
        List<V> newList = new ArrayList<>();
        newList.add(value);
        map.put(key, newList);
    }
    else {
        list.add(value);
    }

    return map;
}

其他回答

如果您选择使用Commons Collections库而不是标准的Java Collections框架,则可以轻松实现这一点。

Collections库中的BidiMap接口是一个双向映射,允许您将一个键映射到一个值(像法线映射一样),也允许您将一个值映射到一个键,从而允许您在两个方向上执行查找。getKey()方法支持为值获取键。

但有一个警告,bidi映射不能有多个值映射到键,因此,除非您的数据集在键和值之间有1:1的映射,否则不能使用bidi映射。


如果您希望依赖Java Collections API,那么在将值插入映射时,必须确保键和值之间的1:1关系。说起来容易做起来难。

一旦您能够确保这一点,就可以使用entrySet()方法获取Map中的条目(映射)集。一旦您获得了类型为Map的集合。条目,遍历条目,将存储的值与预期的值进行比较,并获得相应的键。


对带泛型的bidi映射的支持可以在谷歌Guava和重构的Commons-Collections库中找到(后者不是Apache项目)。感谢Esko指出Apache Commons Collections中缺少的泛型支持。使用带有泛型的集合使代码更具可维护性。


从4.0版开始,官方Apache Commons Collections™库支持泛型。

请参阅“org.apache.commons.collections4.bidimap”包的摘要页,了解BidiMap、OrderedBidiMap和SortedBidiMap接口的可用实现列表,这些接口现在支持Java泛型。

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

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

对于针对API < 19的Android开发,Vitalii Fedorenko一对一关系解决方案无法工作,因为对象。Equals没有实现。这里有一个简单的替代方案:

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

你可以使用下面的:

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