valor recorrer obtener listas leer datos java lambda java-8 java-stream optional

recorrer - obtener valor de un map java



Java 8 extrae la primera clave del valor coincidente en un mapa (6)

A continuación se muestra mi fragmento de código para obtener la clave del mapa,

Map<String,String> pageDetails = new HashMap<String,String>(); public String getAssociatedKey(){ pageDetails.entrySet().stream().filter( e -> e.getValue().contains("John").findFirst().get().getKey(); }

Supongamos que tengo un mapa con el nombre dado, los pares de apellidos y quiero encontrar el nombre de la primera entrada en ese mapa que tenga el apellido que coincida con un determinado valor. ¿Cómo haríamos esto de una manera java 8?

En mi ejemplo de caso de prueba a continuación pongo dos formas de hacerlo.

Sin embargo, el primero (buscando el nombre de pila de la primera persona con el apellido "Donkey") lanzará java.util.NoSuchElementException: no hay valor presente, por lo que no es seguro.

El segundo funciona, pero no solo es más difícil de leer, sino que es un poco poco funcional.

Solo me pregunto si alguien aquí me sugeriría una forma más fácil y clara de lograr esto usando stream() o forEach() o ambos.

@Test public void shouldBeAbleToReturnTheKeyOfTheFirstMatchingValue() throws Exception { Map<String, String> names = new LinkedHashMap<>(); names.put("John", "Doe"); names.put("Fred", "Flintstone"); names.put("Jane", "Doe"); String keyOfTheFirst = names.entrySet().stream().filter(e -> e.getValue().equals("Doe")).findFirst().get().getKey(); assertEquals("John", keyOfTheFirst); try { names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst().get(); } catch (NoSuchElementException e){ // Expected } Optional<Map.Entry<String, String>> optionalEntry = names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst(); keyOfTheFirst = optionalEntry.isPresent() ? optionalEntry.get().getKey() : null; assertNull(keyOfTheFirst); }

Gracias de antemano.


De una question similar:

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

Luego puedes seleccionar el primero, si lo deseas. Recuerde que la key es única, el value no lo es.

Edición: Todo el código (gracias @Peter Lawrey)

package test; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; public class Main { public static void main(String[] args) { Map<String, String> names = new LinkedHashMap<>(); names.put("John", "Doe"); names.put("Fred", "Flintstone"); names.put("Jane", "Doe"); Optional<String> firstKey = names.entrySet().stream() .filter(entry -> Objects.equals(entry.getValue(), "Doe")) .map(Map.Entry::getKey).findFirst(); if (firstKey.isPresent()) { System.out.println(firstKey.get()); } } }


La solución proporcionada por @Misha es la mejor si no desea utilizar el código de terceros. Mi biblioteca tiene el método de método abreviado especial de ofKeys para los casos en que descubrí que es una tarea bastante común:

StreamEx.ofKeys(names, "Donkey"::equals).findFirst().orElse(null);


Me gusta la antigua

static <K, V> K findFirstKeyByValue(Map<K, V> map, String value) { for (Entry<K, V> e : map.entrySet()) if (e.getValue().equals(value)) return e.getKey(); return null; }


Para devolver un valor predeterminado si no hay coincidencia, use Optional#orElse

names.entrySet().stream() .filter(e -> e.getValue().equals("Donkey")) .map(Map.Entry::getKey) .findFirst() .orElse(null);


Para evitar la excepción de puntero nulo si existe una entrada de mapa con un valor nulo:

private String getValueByKey(Map<String, String> map, String key) { return map.entrySet().stream().filter(e -> StringUtils.equalsIgnoreCase(e.getKey(), key)).findFirst().get() .getValue(); }