valores - obtener valor de hashmap java




Java Hashmap: ¿Cómo obtener la clave del valor? (20)

  1. 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.

  2. 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> consultando T.row(a); , y también puede obtener el map<A,C> consultando T.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:

  1. Puede usar múltiples valores.
  2. 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 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);
    }
}

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

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() .


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 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 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.


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

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

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




hashmap