recorre - Java Hashmap: ¿Cómo obtener la clave del valor?
map string string java (30)
Si desea obtener la clave del valor, lo mejor es utilizar bidimap (mapas bidireccionales), puede obtener la clave del valor en O (1) vez.
Pero, el inconveniente de esto es que solo puede usar conjuntos de valores y conjuntos de teclas únicos.
Hay una estructura de datos llamada Tabla en java, que no es más que un mapa de mapas como
Tabla <A, B, C> == mapa <A, mapa <B, C>>
Aquí puede obtener el
map<B,C>
consultandoT.row(a);
, y también puede obtener elmap<A,C>
consultandoT.column(b);
En su caso especial, inserte C como alguna constante.
Entonces, es como <a1, b1, 1> <a2, b2, 1>, ...
Por lo tanto, si encuentra vía T.row (a1) ---> devuelve el mapa de -> obtener keyset este mapa devuelto.
Si necesita encontrar un valor clave, T.column (b2) -> devuelve el mapa de -> obtener el conjunto de claves del mapa devuelto.
Ventajas sobre el caso anterior:
- Puede usar múltiples valores.
- Más eficiente cuando se utilizan grandes conjuntos de datos.
Si tengo el valor "foo"
y un HashMap<String> ftw
para el cual ftw.containsValue("foo")
devuelve true
, ¿cómo puedo obtener la clave correspondiente? ¿Tengo que recorrer el hashmap? ¿Cuál es la mejor manera de hacer eso?
Creo que keySet () puede ser bueno para encontrar la asignación de claves al valor, y tener un mejor estilo de codificación que entrySet () .
Ex:
Supongamos que tiene un mapa HashMap, ArrayList res , un valor en el que desea encontrar toda la asignación de claves , luego almacene las claves en la resolución .
Puedes escribir el código a continuación:
for (int key : map.keySet()) {
if (map.get(key) == value) {
res.add(key);
}
}
en lugar de utilizar entrySet () a continuación:
for (Map.Entry s : map.entrySet()) {
if ((int)s.getValue() == value) {
res.add((int)s.getKey());
}
}
Espero eso ayude :)
Creo que esta es la mejor solución, dirección original: 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;
}
}
Un uso fácil: si pones todos los datos en hasMap y tienes item = "Automobile", entonces estás buscando su clave en hashMap. Esa es una buena solución.
getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
Creo que tus elecciones son
- Utilice una implementación de mapa creada para esto, como el BiMap de las colecciones de Google. Tenga en cuenta que las colecciones de Google BiMap requieren valores y claves inigualables, pero proporciona un alto rendimiento en ambas direcciones.
- Mantenga manualmente dos mapas: uno para clave -> valor, y otro mapa para valor -> clave
- Iterar a través del
entrySet()
y encontrar las claves que coinciden con el valor. Este es el método más lento, ya que requiere iterar a través de toda la colección, mientras que los otros dos métodos no lo requieren.
Decora el mapa con tu propia implementación.
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);
}
}
En java8
map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
.forEach(entry -> System.out.println(entry.getKey()));
Es importante tener en cuenta que, desde esta pregunta, las colecciones Apache son compatibles con los commons.apache.org/proper/commons-collections/javadocs/… . Así que algunas de las respuestas más votadas ya no son precisas en ese punto.
Para un BidiMap serializado que también admite valores duplicados (escenario de 1 a muchos) también considere MapDB.org .
Me temo que tendrás que iterar tu mapa. Lo más corto que pude encontrar:
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();
}
}
Mis 2 centavos. Puede obtener las claves en una matriz y luego hacer un ciclo a través de la matriz. Esto afectará el rendimiento de este bloque de código si el mapa es bastante grande, donde en primer lugar está obteniendo las claves en una matriz, lo que puede consumir algo de tiempo y luego se está realizando un ciclo. De lo contrario, para mapas más pequeños debería estar bien.
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)
}
No hay una respuesta inequívoca, porque varias claves pueden asignarse al mismo valor. Si está aplicando la exclusividad con su propio código, la mejor solución es crear una clase que use dos Hashmaps para rastrear las asignaciones en ambas direcciones.
Para encontrar todas las claves que se asignan a ese valor, itere a través de todos los pares en el hashmap, usando map.entrySet()
.
Para la API de desarrollo de Android <19, la solución de relación uno a uno de Vitalii Fedorenko no funciona porque Objects.equals
no está implementado. Aquí hay una alternativa simple:
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;
}
Parece que la mejor forma de hacerlo es iterar sobre las entradas usando map.entrySet()
ya que map.containsValue()
probablemente haga esto de todos modos.
Puede insertar la clave, el par de valores y su inverso en la estructura de su mapa
map.put("theKey", "theValue");
map.put("theValue", "theKey");
El uso de map.get ("theValue") devolverá "theKey".
Es una forma rápida y sucia de hacer mapas constantes, que solo funcionarán para unos pocos conjuntos de datos seleccionados:
- Contiene solo 1 a 1 pares
- El conjunto de valores está separado del conjunto de claves (1-> 2, 2-> 3 lo rompe)
Puede obtener la clave usando los valores usando el siguiente código ...
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);
Puede utilizar el siguiente:
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);
}
}
}
}
Sí, tienes que recorrer el hashmap, a menos que implementes algo en la línea de lo que sugieren estas diversas respuestas. En lugar de juguetear con el entrySet, obtendría el KeySet (), iteraría sobre ese conjunto y mantendría la (primera) clave que le da su valor coincidente. Si necesita todas las claves que coinciden con ese valor, obviamente tiene que hacer todo el proceso.
Como sugiere Jonas, esto podría ser lo que está haciendo el método contentsValue, por lo que puede omitir esa prueba de forma conjunta y hacer la iteración cada vez (o quizás el compilador ya eliminará la redundancia, quién sabe).
Además, en relación con las otras respuestas, si su mapa inverso parece
Map<Value, Set<Key>>
puede tratar con asignaciones de valor-> clave no únicas, si necesita esa capacidad (desenredándolas a un lado). Eso se incorporaría bien en cualquiera de las soluciones que la gente sugiere aquí usando dos mapas.
Si bien esto no responde directamente a la pregunta, está relacionado.
De esta manera no necesitas seguir creando / iterando. Solo crea un mapa inverso una vez y obtén lo que necesitas.
/**
* 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;
}
Si crea el mapa en su propio código, intente juntar la clave y el valor en el mapa:
public class KeyValue {
public Object key;
public Object value;
public KeyValue(Object key, Object value) { ... }
}
map.put(key, new KeyValue(key, value));
Luego, cuando tienes un valor, también tienes la clave.
Si elige utilizar la biblioteca de colecciones de Commons en lugar de la API de colecciones de Java estándar, puede lograrlo con facilidad.
La interfaz BidiMap en la biblioteca de colecciones es un mapa bidireccional, que le permite asignar una clave a un valor (como los mapas normales) y también a un valor de una clave, lo que le permite realizar búsquedas en ambas direcciones. La obtención de una clave para un valor es compatible con el método getKey () .
Sin embargo, hay una advertencia, los mapas bidi no pueden tener múltiples valores asignados a las claves y, por lo tanto, a menos que su conjunto de datos tenga asignaciones 1: 1 entre las claves y los valores, no puede usar los mapas de bid.
Actualizar
Si desea confiar en la Java Collections API, deberá garantizar la relación 1: 1 entre las claves y los valores al momento de insertar el valor en el mapa. Esto es más fácil dicho que hecho.
Una vez que pueda asegurarse de eso, use el método entrySet () para obtener el conjunto de entradas (mapeos) en el Mapa. Una vez que haya obtenido el conjunto cuyo tipo es Map.Entry , Map.Entry las entradas, compare el valor almacenado con el esperado y obtenga la clave correspondiente .
Actualización # 2
El soporte para mapas bidi con genéricos se puede encontrar en Google Guava y en las bibliotecas de las Commons-Collections refactored (esta última no es un proyecto de Apache). Gracias a Esko por señalar el soporte genérico faltante en Apache Commons Collections. Usar colecciones con genéricos hace que el código sea más mantenible.
Si su estructura de datos tiene una asignación de muchos a uno entre claves y valores, debe repetir las entradas y seleccionar todas las claves adecuadas:
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;
}
En el caso de una relación uno a uno , puede devolver la primera clave coincidente:
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;
}
En 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());
}
Además, para los usuarios de guayaba, BiMap puede ser útil. Por ejemplo:
BiMap<Token, Character> tokenToChar =
ImmutableBiMap.of(Token.LEFT_BRACKET, ''['', Token.LEFT_PARENTHESIS, ''('');
Token token = tokenToChar.inverse().get(''('');
Character c = tokenToChar.get(token);
Use una envoltura delgada: HMap
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class HMap<K, V> {
private final Map<K, Map<K, V>> map;
public HMap() {
map = new HashMap<K, Map<K, V>>();
}
public HMap(final int initialCapacity) {
map = new HashMap<K, Map<K, V>>(initialCapacity);
}
public boolean containsKey(final Object key) {
return map.containsKey(key);
}
public V get(final Object key) {
final Map<K, V> entry = map.get(key);
if (entry != null)
return entry.values().iterator().next();
return null;
}
public K getKey(final Object key) {
final Map<K, V> 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<K, V> entry = map
.put(key, Collections.singletonMap(key, value));
if (entry != null)
return entry.values().iterator().next();
return null;
}
}
Utilizando Java 8:
ftw.forEach((key, value) -> {
if (value=="foo") {
System.out.print(key);
}
});
/**
* This method gets the Key for the given Value
* @param paramName
* @return
*/
private String getKeyForValueFromMap(String paramName) {
String keyForValue = null;
if(paramName!=null)) {
Set<Entry<String,String>> entrySet = myMap().entrySet();
if(entrySet!=null && entrySet.size>0) {
for(Entry<String,String> entry : entrySet) {
if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) {
keyForValue = entry.getKey();
}
}
}
}
return keyForValue;
}
for(int key: hm.keySet()) {
if(hm.get(key).equals(value)) {
System.out.println(key);
}
}
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<String, List<String>> resultHashMap = new HashMap<String, List<String>>();
Set<String> newKeyList = resultHashMap.keySet();
for (Iterator<String> iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) {
String hashKey = (String) iterator.next();
if (!newKeyList.contains(originalHashMap.get(hashKey))) {
List<String> loArrayList = new ArrayList<String>();
loArrayList.add(hashKey);
resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
} else {
List<String> 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);
}
}
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class ValueKeysMap<K, V> extends HashMap <K,V>{
HashMap<V, Set<K>> ValueKeysMap = new HashMap<V, Set<K>>();
@Override
public boolean containsValue(Object value) {
return ValueKeysMap.containsKey(value);
}
@Override
public V put(K key, V value) {
if (containsValue(value)) {
Set<K> keys = ValueKeysMap.get(value);
keys.add(key);
} else {
Set<K> keys = new HashSet<K>();
keys.add(key);
ValueKeysMap.put(value, keys);
}
return super.put(key, value);
}
@Override
public V remove(Object key) {
V value = super.remove(key);
Set<K> keys = ValueKeysMap.get(value);
keys.remove(key);
if(keys.size() == 0) {
ValueKeysMap.remove(value);
}
return value;
}
public Set<K> getKeys4ThisValue(V value){
Set<K> keys = ValueKeysMap.get(value);
return keys;
}
public boolean valueContainsThisKey(K key, V value){
if (containsValue(value)) {
Set<K> keys = ValueKeysMap.get(value);
return keys.contains(key);
}
return false;
}
/*
* Take care of argument constructor and other api''s like putAll
*/
}
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());
}
}
}
}
Alguna información adicional ... Puede ser útil para usted
El método anterior puede no ser bueno si tu hashmap es realmente grande. Si su hashmap contiene una clave única para un mapeo de valor único, puede mantener un hashmap más que contenga una correlación de Value to Key.
Es decir, hay que mantener dos hashmaps.
1. Key to value
2. Value to key
En ese caso, puedes usar el segundo hashmap para obtener la clave.
public static String getKey(Map<String, Integer> mapref, String value) {
String key = "";
for (Map.Entry<String, Integer> map : mapref.entrySet()) {
if (map.getValue().toString().equals(value)) {
key = map.getKey();
}
}
return key;
}
public static class SmartHashMap <T1 extends Object, T2 extends Object> {
public HashMap<T1, T2> keyValue;
public HashMap<T2, T1> valueKey;
public SmartHashMap(){
this.keyValue = new HashMap<T1, T2>();
this.valueKey = new HashMap<T2, T1>();
}
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);
}
}