wake-up-neo.net

Java 8 extrahiert den ersten Schlüssel aus dem übereinstimmenden Wert in einer Map

Angenommen, ich habe eine Karte mit Vornamen und Nachnamenpaaren, und ich möchte den Vornamen des ersten Eintrags in dieser Karte finden, dessen Nachname mit einem bestimmten Wert übereinstimmt. Wie würden wir dies auf eine Java 8-Art tun?.

In meinem Beispiel für den Testfall habe ich zwei Möglichkeiten angegeben.

Die erste (nach dem Vornamen der ersten Person mit dem Nachnamen "Donkey" suchend) wird jedoch Java.util.NoSuchElementException auslösen: Kein Wert vorhanden, daher nicht sicher.

Das zweite funktioniert, aber es ist nicht nur schwieriger zu lesen, sondern es ist auch nicht ganz funktionell.

Ich frage mich nur, ob mir jemand hier einen klareren Weg vorschlägt, dies entweder mit stream() oder forEach() oder mit beiden zu erreichen.

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

Danke im Voraus.

17
Julian

Um einen Standardwert zurückzugeben, wenn keine Übereinstimmung vorliegt, verwenden Sie Optional#orElse

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

Die von @Misha bereitgestellte Lösung ist die beste, wenn Sie den Code von Drittanbietern nicht verwenden möchten. Meine Bibliothek hat die spezielle Abkürzungsmethode ofKeys für die Fälle, in denen ich herausgefunden habe, dass dies eine ganz gewöhnliche Aufgabe ist:

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

Aus einer ähnlichen Frage :

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

Dann können Sie die erste auswählen, wenn Sie möchten. Denken Sie daran, dass key eindeutig ist, value nicht.

Edit: Der ganze Code (Danke @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());
        }
    }
}
0
Doon

Unten ist mein Code-Snippet, um den Schlüssel von der Karte zu erhalten. 

Map<String,String> pageDetails = new HashMap<String,String>();

public String getAssociatedKey(){
pageDetails.entrySet().stream().filter( e -> e.getValue().contains("John").findFirst().get().getKey();
}
0
Pavan T

Um eine Nullzeigerausnahme zu vermeiden, wenn ein Map-Eintrag mit einem Nullwert vorhanden ist:

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

Ich mag altmodisch:

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