如果我有一个值为 "foo"
的变量,并且有一个 HashMap<String> ftw
,其中 ftw.containsValue("foo")
返回 true
,那么如何获取相应的键? 我必须遍历整个 HashMap 吗?最好的方法是什么?
如果你的数据结构中存在键和值之间的 多对一 映射,你应该迭代所有项并选择所有适当的键:
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);
o(1)
。如果您正在遍历值,则会降低性能。如果您想要更好的性能并且具有一对一的关系,则可以使用另一个映射,其中“值是键”。 - veer7.filter(entry -> entry.getValue().equals(value))
жӣҝжҚўдёә .filter(entry ->
Objects.equals
(entry.getValue(), value))
пјҢеӣ дёәжІЎжңүе…ідәҺnull
еҖјзҡ„еЈ°жҳҺгҖӮжӯӨеӨ–пјҢдҪ еҸҜд»Ҙе°Ҷ.map(entry -> entry.getKey())
жӣҝжҚўдёә .map(Map.Entry::getKey)
гҖӮ - HolgerBidiMap
接口是一个双向映射,允许您将键映射到值(像普通映射一样),还可以将值映射到键,从而允许您在两个方向上执行查找。通过getKey()
方法支持获取值的键。entrySet()
方法获取Map中条目(映射)的集合。一旦您获得了类型为Map.Entry
的集合,遍历这些条目,将存储的值与期望值进行比较,并获取相应的键。
支持使用泛型的可以在Google Guava和重构后的Commons-Collections库中找到(后者不是Apache项目)。感谢Esko指出了Apache Commons Collections中缺少泛型支持的问题。使用带有泛型的集合可以使代码更易于维护。
自 version 4.0 版本起,官方的 Apache Commons Collections™ 库支持 泛型。
请参阅 "org.apache.commons.collections4.bidimap" 包的 summary 页面,了解现在支持 Java 泛型 的 BidiMap
、OrderedBidiMap
和 SortedBidiMap
接口的可用实现列表。
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());
}
}
}
}
一些额外的信息...可能对您有用
如果您的哈希映射表非常大,则上面的方法可能并不好。如果您的哈希映射表包含唯一键到唯一值的映射,则可以维护另一个哈希映射表,该表包含从值到键的映射。
也就是说,您需要维护两个哈希映射表。
1. Key to value
2. Value to key
在这种情况下,你可以使用第二个哈希表来获取键。
您可以将键值对及其相反的形式插入到您的映射结构中。
map.put("theKey", "theValue");
map.put("theValue", "theKey");
使用map.get("theValue")将会返回"theKey"。
这是我制作常量映射的一种快速且简单的方法,但仅适用于少量数据集:
我认为你有以下几个选择:
entrySet()
查找与值匹配的键。这是最慢的方法,因为它需要遍历整个集合,而其他两种方法不需要这样做。使用 Java 8:
ftw.forEach((key, value) -> {
if (value.equals("foo")) {
System.out.print(key);
}
});
value
已被内部化,否则为真。 - frododot使用您自己的实现来装饰地图
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);
}
}
我认为这是最好的解决方案,原始地址: 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;
}
}
一个简单的用法:
如果你将所有数据放在HashMap中,而且你有一个项目 =“汽车”,那么你可以在HashMap中查找其键。这是一个很好的解决方案。getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
如果您在自己的代码中构建了Map,请尝试将键和值放在一起:
public class KeyValue {
public Object key;
public Object value;
public KeyValue(Object key, Object value) { ... }
}
map.put(key, new KeyValue(key, value));
当你有一个值时,你也拥有了键。
由于多个键可以映射到同一个值,所以没有明确的答案。如果您想在自己的代码中强制唯一性,则最好的解决方案是创建一个类,使用两个Hashmap跟踪双向映射。
HashMap<String> ftw
中的关键类型。 - user16320675