Java Hashmap:如何从值中获取键?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1383797/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Hashmap: How to get key from value?
提问by Nick Heiner
If I have the value "foo"
, and a HashMap<String> ftw
for which ftw.containsValue("foo")
returns true
, how can I get the corresponding key? Do I have to loop through the hashmap? What is the best way to do that?
如果我有 value"foo"
和 a HashMap<String> ftw
for which ftw.containsValue("foo")
return true
,我怎样才能获得相应的键?我必须遍历哈希图吗?最好的方法是什么?
采纳答案by Vineet Reynolds
If you choose to use the Commons Collections libraryinstead of the standard Java Collections API, you can achieve this with ease.
如果您选择使用Commons Collections 库而不是标准的 Java Collections API,则可以轻松实现这一点。
The BidiMapinterface in the Collections library is a bi-directional map, allowing you to map a key to a value (like normal maps), and also to map a value to a key, thus allowing you to perform lookups in both directions. Obtaining a key for a value is supported by the getKey() method.
Collections 库中的BidiMap接口是一个双向映射,允许您将键映射到值(如法线映射),也可以将值映射到键,从而允许您在两个方向上执行查找。getKey() 方法支持获取值的键。
There is a caveat though, bidi maps cannot have multiple values mapped to keys, and hence unless your data set has 1:1 mappings between keys and values, you cannot use bidimaps.
但是有一个警告,bidi 映射不能将多个值映射到键,因此除非您的数据集在键和值之间具有 1:1 映射,否则您不能使用 bidimap。
Update
更新
If you want to rely on the Java Collections API, you will have to ensure the 1:1 relationship between keys and values at the time of inserting the value into the map. This is easier said than done.
如果要依赖 Java Collections API,则必须在将值插入映射时确保键和值之间的 1:1 关系。这说起来容易做起来难。
Once you can ensure that, use the entrySet() methodto obtain the set of entries (mappings) in the Map. Once you have obtained the set whose type is Map.Entry, iterate through the entries, comparing the stored valueagainst the expected, and obtain the corresponding key.
一旦可以确保,使用entrySet() 方法获取 Map 中的条目集(映射)。获得类型为Map.Entry的集合后,遍历条目,将存储的值与预期值进行比较,并获得相应的 key。
Update #2
更新 #2
Support for bidi maps with generics can be found in Google Guavaand the refactored Commons-Collectionslibraries (the latter is not an Apache project). Thanks to Esko for pointing out the missing generic support in Apache Commons Collections. Using collections with generics makes more maintainable code.
可以在Google Guava和重构的Commons-Collections库(后者不是 Apache 项目)中找到对具有泛型的双向映射的支持。感谢 Esko 指出 Apache Commons Collections 中缺少的通用支持。使用带有泛型的集合可以使代码更易于维护。
回答by recursive
There is no unambiguous answer, because multiple keys can map to the same value. If you are enforcing unique-ness with your own code, the best solution is to create a class that uses two Hashmaps to track the mappings in both directions.
没有明确的答案,因为多个键可以映射到相同的值。如果您使用自己的代码强制执行唯一性,最好的解决方案是创建一个类,该类使用两个 Hashmap 来跟踪两个方向的映射。
回答by wsorenson
To find all the keys that map to that value, iterate through all the pairs in the hashmap, using map.entrySet()
.
要查找映射到该值的所有键,请使用map.entrySet()
.
回答by Jonas K
It sounds like the best way is for you to iterate over entries using map.entrySet()
since map.containsValue()
probably does this anyway.
听起来最好的方法是让您使用迭代条目,map.entrySet()
因为map.containsValue()
无论如何可能会这样做。
回答by Chi
I think your choices are
我认为你的选择是
- Use a map implementation built for this, like the BiMapfrom google collections. Note that the google collections BiMap requires uniqueless of values, as well as keys, but it provides high performance in both directions performance
- Manually maintain two maps - one for key -> value, and another map for value -> key
- Iterate through the
entrySet()
and to find the keys which match the value. This is the slowest method, since it requires iterating through the entire collection, while the other two methods don't require that.
- 使用为此构建的地图实现,例如来自谷歌集合的BiMap。请注意,谷歌集合 BiMap 需要唯一的值和键,但它提供了双向性能的高性能
- 手动维护两个映射 - 一个用于键 -> 值,另一个映射用于值 -> 键
- 遍历
entrySet()
和 以找到与值匹配的键。这是最慢的方法,因为它需要遍历整个集合,而其他两种方法不需要。
回答by David Tinker
If you build the map in your own code, try putting the key and value in the map together:
如果您在自己的代码中构建地图,请尝试将地图中的键和值放在一起:
public class KeyValue {
public Object key;
public Object value;
public KeyValue(Object key, Object value) { ... }
}
map.put(key, new KeyValue(key, value));
Then when you have a value, you also have the key.
然后,当您拥有价值时,您也拥有了钥匙。
回答by Carl
Yes, you have to loop through the hashmap, unless you implement something along the lines of what these various answers suggest. Rather than fiddling with the entrySet, I'd just get the keySet(), iterate over that set, and keep the (first) key that gets you your matching value. If you need all the keys that match that value, obviously you have to do the whole thing.
是的,您必须遍历哈希图,除非您按照这些不同答案所建议的方式实现某些内容。而不是摆弄 entrySet,我只需要获取 keySet(),迭代该集合,并保留获得匹配值的(第一个)键。如果您需要与该值匹配的所有键,显然您必须做整件事。
As Jonas suggests, this might already be what the containsValue method is doing, so you might just skip that test all-together, and just do the iteration every time (or maybe the compiler will already eliminate the redundancy, who knows).
正如 Jonas 所建议的,这可能已经是 containsValue 方法正在执行的操作,因此您可能只是一起跳过该测试,并且每次都进行迭代(或者编译器可能已经消除了冗余,谁知道呢)。
Also, relative to the other answers, if your reverse map looks like
另外,相对于其他答案,如果您的反向地图看起来像
Map<Value, Set<Key>>
you can deal with non-unique key->value mappings, if you need that capability (untangling them aside). That would incorporate fine into any of the solutions people suggest here using two maps.
如果您需要该功能(将它们解开),您可以处理非唯一键-> 值映射。这将很好地融入人们在这里使用两张地图建议的任何解决方案中。
回答by Vitalii Fedorenko
If your data structure has many-to-onemapping between keys and values you should iterate over entries and pick all suitable keys:
如果您的数据结构在键和值之间具有多对一映射,您应该迭代条目并选择所有合适的键:
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;
}
In case of one-to-onerelationship, you can return the first matched key:
在一对一关系的情况下,您可以返回第一个匹配的键:
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;
}
In Java 8:
在 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());
}
Also, for Guava users, BiMapmay be useful. For example:
此外,对于 Guava 用户,BiMap可能很有用。例如:
BiMap<Token, Character> tokenToChar =
ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);
回答by André van Toly
I'm afraid you'll just have to iterate your map. Shortest I could come up with:
恐怕你只需要迭代你的地图。我能想到的最短时间:
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();
}
}
回答by Amit
You can get the key using values using following code..
您可以使用以下代码使用值获取密钥..
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);