本文共 13765 字,大约阅读时间需要 45 分钟。
如果我的值是"foo"
,并且ftw.containsValue("foo")
返回true
的<String> ftw
,如何获得相应的键? 我是否必须遍历哈希图? 最好的方法是什么?
import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Set;public class M{public static void main(String[] args) { HashMap> resultHashMap = new HashMap >(); Set newKeyList = resultHashMap.keySet(); for (Iterator iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) { String hashKey = (String) iterator.next(); if (!newKeyList.contains(originalHashMap.get(hashKey))) { List loArrayList = new ArrayList (); loArrayList.add(hashKey); resultHashMap.put(originalHashMap.get(hashKey), loArrayList); } else { List loArrayList = resultHashMap.get(originalHashMap .get(hashKey)); loArrayList.add(hashKey); resultHashMap.put(originalHashMap.get(hashKey), loArrayList); } } System.out.println("Original HashMap : " + originalHashMap); System.out.println("Result HashMap : " + resultHashMap); }}
没有明确的答案,因为多个键可以映射到相同的值。 如果要使用自己的代码强制唯一性,则最佳解决方案是创建一个使用两个Hashmap来跟踪两个方向上的映射的类。
要查找映射到该值的所有键,请使用map.entrySet()
遍历哈希图中的所有对。
听起来最好的方法是使用map.entrySet()
遍历条目,因为map.containsValue()
可能还是这样做。
如果您选择使用而不是标准Java Collections API,则可以轻松实现此目的。
Collections库中的接口是双向映射,允许您将键映射到值(如法线映射),也可以将值映射到键,从而允许您在两个方向上执行查找。 支持获取值的键。
需要注意的是,bidi映射不能将多个值映射到键,因此,除非您的数据集在键和值之间具有1:1映射,否则您不能使用bidimaps。
更新资料
如果要依赖Java Collections API,则必须在将值插入映射时确保键和值之间的1:1关系。 说起来容易做起来难。
一旦可以确保使用,请使用获取Map中的一组条目(映射)。 获得类型为的集合后,请遍历条目,将与期望值进行比较,并获得 。
更新#2
可以在和重构的库(后者不是Apache项目)中找到对带有泛型的比迪地图的支持。 感谢Esko指出Apache Commons Collections中缺少的通用支持。 将集合与泛型一起使用可使代码更易于维护。
我认为你的选择是
entrySet()
并找到与该值匹配的键。 这是最慢的方法,因为它需要遍历整个集合,而其他两种方法则不需要。 如果您使用自己的代码构建地图,请尝试将键和值放到地图中:
public class KeyValue { public Object key; public Object value; public KeyValue(Object key, Object value) { ... }}map.put(key, new KeyValue(key, value));
然后,当您拥有一个值时,您也将拥有钥匙。
是的,除非您按照这些不同答案所建议的方式实施某些操作,否则您必须遍历哈希图。 我只需要获取keySet(),然后遍历该集合,然后保留(第一个)键即可获得匹配的值,而不必摆弄entrySet。 如果您需要与该值匹配的所有键,那么显然您必须做整个事情。
正如乔纳斯(Jonas)所建议的那样,这可能已经是containsValue方法的作用,因此您可能会完全跳过该测试,并且每次都进行迭代(或者,编译器已经消除了冗余,这是众所周知的)。
另外,相对于其他答案,如果您的反向映射看起来像
Map>
如果需要此功能,则可以处理非唯一的key-> value映射(将它们放在一边)。 这可以很好地结合到人们使用两个地图建议的任何解决方案中。
public static class SmartHashMap{ public HashMap keyValue; public HashMap valueKey; public SmartHashMap(){ this.keyValue = new HashMap (); this.valueKey = new HashMap (); } public void add(T1 key, T2 value){ this.keyValue.put(key, value); this.valueKey.put(value, key); } public T2 getValue(T1 key){ return this.keyValue.get(key); } public T1 getKey(T2 value){ return this.valueKey.get(value); }}
import java.util.HashMap;import java.util.HashSet;import java.util.Set;public class ValueKeysMapextends HashMap { HashMap > ValueKeysMap = new HashMap >(); @Override public boolean containsValue(Object value) { return ValueKeysMap.containsKey(value); } @Override public V put(K key, V value) { if (containsValue(value)) { Set keys = ValueKeysMap.get(value); keys.add(key); } else { Set keys = new HashSet (); keys.add(key); ValueKeysMap.put(value, keys); } return super.put(key, value); } @Override public V remove(Object key) { V value = super.remove(key); Set keys = ValueKeysMap.get(value); keys.remove(key); if(keys.size() == 0) { ValueKeysMap.remove(value); } return value; } public Set getKeys4ThisValue(V value){ Set keys = ValueKeysMap.get(value); return keys; } public boolean valueContainsThisKey(K key, V value){ if (containsValue(value)) { Set keys = ValueKeysMap.get(value); return keys.contains(key); } return false; } /* * Take care of argument constructor and other api's like putAll */}
您可以将键,值对及其反向插入到地图结构中
map.put("theKey", "theValue");map.put("theValue", "theKey");
然后使用map.get(“ theValue”)将返回“ theKey”。
我制作了常量映射是一种快速而肮脏的方法,它仅适用于少数几个数据集:
在java8中
map.entrySet().stream().filter(entry -> entry.getValue().equals(value)) .forEach(entry -> System.out.println(entry.getKey()));
我认为这是最好的解决方案,原始地址:
import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] argv) { Mapmap = new HashMap (); 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; } }
一种简单的用法:如果将所有数据都放入hasMap中,并且具有item =“ Automobile”,那么您将在hashMap中查找其键。 那是很好的解决方案。
getKeyFromValue(hashMap, item);System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
如果您的数据结构在键和值之间具有多对一映射,则应遍历条目并选择所有合适的键:
public staticSet getKeysByValue(Map map, E value) { Set keys = new HashSet (); for (Entry entry : map.entrySet()) { if (Objects.equals(value, entry.getValue())) { keys.add(entry.getKey()); } } return keys;}
如果是一对一关系,则可以返回第一个匹配的键:
public staticT getKeyByValue(Map map, E value) { for (Entry entry : map.entrySet()) { if (Objects.equals(value, entry.getValue())) { return entry.getKey(); } } return null;}
在Java 8中:
public staticSet getKeysByValue(Map map, E value) { return map.entrySet() .stream() .filter(entry -> Objects.equals(entry.getValue(), value)) .map(Map.Entry::getKey) .collect(Collectors.toSet());}
同样,对于Guava用户, 可能会有用。 例如:
BiMaptokenToChar = ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');Token token = tokenToChar.inverse().get('(');Character c = tokenToChar.get(token);
恐怕您只需要迭代地图即可。 我能想到的最短的时间是:
Iterator> iter = map.entrySet().iterator();while (iter.hasNext()) { Map.Entry entry = iter.next(); if (entry.getValue().equals(value_you_look_for)) { String key_you_look_for = entry.getKey(); }}
/** * This method gets the Key for the given Value * @param paramName * @return */private String getKeyForValueFromMap(String paramName) { String keyForValue = null; if(paramName!=null)) { Set> entrySet = myMap().entrySet(); if(entrySet!=null && entrySet.size>0) { for(Entry entry : entrySet) { if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) { keyForValue = entry.getKey(); } } } } return keyForValue;}
您可以使用以下代码使用值来获取密钥。
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);
值得注意的是,由于这个问题,Apache Collections支持 。 因此,在这一点上,一些投票最多的答案不再准确。
对于也支持重复值的序列化BidiMap(一对多方案),请考虑 。
for(int key: hm.keySet()) { if(hm.get(key).equals(value)) { System.out.println(key); }}
使用Java 8:
ftw.forEach((key, value) -> { if (value.equals("foo")) { System.out.print(key); }});
对于面向API <19的Android开发,Vitalii Fedorenko一对一关系解决方案不起作用,因为未实现Objects.equals
。 这是一个简单的选择:
publicK getKeyByValue(Map map, V value) { for (Map.Entry entry : map.entrySet()) { if (value.equals(entry.getValue())) { return entry.getKey(); } } return null;}
用自己的实现装饰地图
class MyMapextends HashMap { Map reverseMap = new HashMap (); @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); }}
我的2美分。 您可以获取数组中的键,然后在数组中循环。 如果映射很大,这将影响此代码块的性能,在这种情况下,您首先要获取数组中的键,这可能会花费一些时间,然后循环。 否则,对于较小的地图应该没问题。
String[] keys = yourMap.keySet().toArray(new String[0]);for(int i = 0 ; i < keys.length ; i++){ //This is your key String key = keys[i]; //This is your value yourMap.get(key) }
如果要从值中获取密钥,最好使用bidimap(双向映射),则可以在O(1)时间内从值中获取密钥。
但是,这样做的缺点是您只能使用唯一的键集和值集。
Java中有一个名为Table的数据结构,它不过是类似map的map
表格<A,B,C> ==映射<A,映射<B,C>>
在这里,您可以通过查询T.row(a);
获得map<B,C>
T.row(a);
,还可以通过查询T.column(b);
获得map<A,C>
T.column(b);
在特殊情况下,将C插入为常数。
因此,它类似于<a1,b1,1> <a2,b2,1>,...
因此,如果通过T.row(a1)查找--->返回->的映射,则获取此返回映射的键集。
如果需要查找键值,则T.column(b2)->返回->的映射,获取返回映射的键集。
与以前相比的优势:
您可以使用以下内容:
public class HashmapKeyExist { public static void main(String[] args) { HashMaphmap = new HashMap (); 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); } } }}
public static String getKey(Mapmapref, String value) { String key = ""; for (Map.Entry map : mapref.entrySet()) { if (map.getValue().toString().equals(value)) { key = map.getKey(); } } return key;}
我认为keySet()可能很好地找到映射到该值的键,并且比entrySet()更好的编码风格。
例如:
假设您有一个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()); } }
希望能帮助到你 :)
尽管这并不能直接回答问题,但却是相关的。
这样,您无需继续创建/迭代。 只需创建一次反向映射即可获得所需的内容。
/** * 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* @param * @return */public static Map > reverseMap(Map map) { if(map == null) return null; Map > reverseMap = new ArrayMap<>(); for(Map.Entry 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 * @param * @return */public static Map > appendValueToMapList(Map > map, K key, V value) { if(map == null || key == null || value == null) return map; List list = map.get(key); if(list == null) { List newList = new ArrayList<>(); newList.add(value); map.put(key, newList); } else { list.add(value); } return map;}
public class NewClass1 { public static void main(String[] args) { MaptestMap = new HashMap (); testMap.put(10, "a"); testMap.put(20, "b"); testMap.put(30, "c"); testMap.put(40, "d"); for (Entry entry : testMap.entrySet()) { if (entry.getValue().equals("c")) { System.out.println(entry.getKey()); } } }}
一些其他信息...可能对您有用
如果您的哈希图很大,则上述方法可能不是很好。 如果您的哈希表包含唯一键到唯一值的映射,则可以再维护一个哈希表,其中包含从值到键的映射。
那就是你必须维护两个哈希图
1. Key to value2. Value to key
在这种情况下,您可以使用第二个哈希图来获取密钥。
使用薄包装器:
import java.util.Collections;import java.util.HashMap;import java.util.Map;public class HMap{ private final Map > map; public HMap() { map = new HashMap >(); } public HMap(final int initialCapacity) { map = new HashMap >(initialCapacity); } public boolean containsKey(final Object key) { return map.containsKey(key); } public V get(final Object key) { final Map entry = map.get(key); if (entry != null) return entry.values().iterator().next(); return null; } public K getKey(final Object key) { final Map entry = map.get(key); if (entry != null) return entry.keySet().iterator().next(); return null; } public V put(final K key, final V value) { final Map entry = map .put(key, Collections.singletonMap(key, value)); if (entry != null) return entry.values().iterator().next(); return null; }}
转载地址:http://iwcnb.baihongyu.com/