2015-04-14 8 views
23

HashMap mit Streams in Java 8 Streams Wert von Karte sammeln

Map<Integer, List> id1 = new HashMap<Integer,List>(); 

ich hashmap betrachten Lassen Sie einige Werte in beiden hashmap eingefügt.

Zum Beispiel

List<String> list1 = new ArrayList<String>(); 

    list1.add("r1"); 
    list1.add("r4"); 

    List<String> list2 = new ArrayList<String>(); 
    list2.add("r2"); 
    list2.add("r5"); 

    List<String> list3 = new ArrayList<String>(); 
    list3.add("r3"); 
    list3.add("r6"); 

    id1.put(1,list1); 
    id1.put(2,list2); 
    id1.put(3,list3); 
    id1.put(10,list2); 
    id1.put(15,list3); 

Q1) Jetzt möchte ich eine Filterbedingung auf dem Schlüssel in hashmap anzuwenden und den entsprechenden Wert (List) abrufen.

Beispiel: Hier Meine Abfrage ist der Schlüssel = 1 und Ausgabe sollte ‚list1‘ sein

Ich schrieb

id1.entrySet().stream().filter(e -> e.getKey() == 1); 

Aber ich weiß nicht, wie als Liste als Ausgang dieses abrufen Stream-Betrieb.

Q2) Wieder möchte ich eine Filterbedingung auf den Schlüssel in hashmap anwenden und die entsprechende Liste der Listen abrufen.

ZB: Hier Meine Abfrage ist Schlüssel = 1% (d. H. Schlüssel kann 1,10,15 sein), und die Ausgabe sollte 'list1', 'list2', 'list3' (Liste von Listen) sein.

+4

Verwenden Sie keine halb gebackenen generischen Typen. Höchstwahrscheinlich sollte Ihre Karte 'Map >' anstatt 'Map ' – Holger

Antwort

40

Wenn Sie sicher sind Sie höchstens ein einzelnes Element erhalten werden, die den Filter passiert (die durch den Filter gewährleistet ist), können Sie findFirst verwenden:

Optional<List> o = id1.entrySet() 
         .stream() 
         .filter(e -> e.getKey() == 1) 
         .map(Map.Entry::getValue) 
         .findFirst(); 

Im allgemeinen Fall, wenn die Filter können mehrere Listen übereinstimmen, können Sie sie auf eine Liste der Listen sammeln können:

List<List> list = id1.entrySet() 
        .stream() 
        .filter(.. some predicate...) 
        .map(Map.Entry::getValue) 
        .collect(Collectors.toList()); 
+1

sein. Sie haben vergessen, '.map (Map.Entry :: getValue)') – fge

+0

@fge danke. .. – Eran

15

Was müssen Sie tun, ist eine Stream aus der .entrySet() s Map‘erstellen:

// Map<K, V> --> Set<Map.Entry<K, V>> --> Stream<Map.Entry<K, V>> 
map.entrySet().stream() 

Von dem auf, können Sie .filter() über diese Einträge. Zum Beispiel:

// Stream<Map.Entry<K, V>> --> Stream<Map.Entry<K, V>> 
.filter(entry -> entry.getKey() == 1) 

Und die Werte aus es Sie .map() zu erhalten:

// Stream<Map.Entry<K, V>> --> Stream<V> 
.map(Map.Entry::getValue) 

Schließlich müssen Sie in eine List sammeln:

// Stream<V> --> List<V> 
.collect(Collectors.toList()) 

Wenn Sie nur einen Eintrag haben , verwenden Sie diese stattdessen (Hinweis: dieser Code setzt voraus, dass ein Wert vorhanden ist; andernfalls verwenden Sie .orElse(); weitere Informationen finden Sie unter javadoc of Optional):

// Stream<V> --> Optional<V> --> V 
.findFirst().get() 
+0

@ user2336315 ja, dieser Code setzt voraus, dass der Wert existiert; OP ist nicht sehr klar darüber. Ah, gut – fge

4

Für Ihr Q2 gibt es bereits Antworten auf Ihre Frage. Für Ihr Q1 und allgemein, wenn Sie wissen, dass die Filterung des Schlüssels einen einzigartigen Wert geben sollte, müssen Sie überhaupt keine Streams verwenden.

Verwenden Sie einfach get oder getOrDefault, ich.e:

List<String> list1 = id1.getOrDefault(1, Collections.emptyList()); 
1

Sie können es auch tun, wie diese

public Map<Boolean, List<Student>> getpartitionMap(List<Student> studentsList) { 

    List<Predicate<Student>> allPredicates = getAllPredicates(); 
    Predicate<Student> compositePredicate = allPredicates.stream() 
          .reduce(w -> true, Predicate::and) 
    Map<Boolean, List<Student>> studentsMap= studentsList 
       .stream() 
       .collect(Collectors.partitioningBy(compositePredicate)); 
    return studentsMap; 
} 

public List<Student> getValidStudentsList(Map<Boolean, List<Student>> studentsMap) throws Exception { 

    List<Student> validStudentsList = studentsMap.entrySet() 
      .stream() 
      .filter(p -> p.getKey() == Boolean.TRUE) 
      .flatMap(p -> p.getValue().stream()) 
      .collect(Collectors.toList()); 

    return validStudentsList; 
} 

public List<Student> getInValidStudentsList(Map<Boolean, List<Student>> studentsMap) throws Exception { 

    List<Student> invalidStudentsList = 
      partionedByPredicate.entrySet() 
      .stream() 
      .filter(p -> p.getKey() == Boolean.FALSE) 
      .flatMap(p -> p.getValue().stream()) 
      .collect(Collectors.toList()); 

    return invalidStudentsList; 

} 

Mit flatMap werden Sie nur List<Student> statt List<List<Student>> bekommen.

Danke