2015-08-20 6 views
5

Ich habe die folgende Liste der Karten,Wie die Mindestpunktzahl der einzelnen Benutzer aus einer Liste von Karten finden mit Hilfe von Java 8 Stream

List<Map<String, Integer>> scores = new ArrayList<>(); 

scores.add(Collections.singletonMap("user1", 3)); 
scores.add(Collections.singletonMap("user3", 15)); 
scores.add(Collections.singletonMap("user1", 1)); 
scores.add(Collections.singletonMap("user2", 5)); 
scores.add(Collections.singletonMap("user2", 23)); 
scores.add(Collections.singletonMap("user1", 10)); 

Angenommen, ich mag die minumum Score von jedem Benutzer in eine extrahieren Karte mit Java 8 Stream mit Lambda-Ausdrücken. Das gewünschte Ergebnis würde

{user1=1, user2=5, user3=15} 

Ich versuchte dies und es funktioniert nicht,

Map<String, Integer> result = scores.stream() 
    .flatMap(m -> m.entrySet().stream()) 
    .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.minBy(Comparator.comparingInt(Map.Entry::getValue)))); 

Könnte jemand bitte sagen Sie mir, wie es zu tun?

Vielen Dank im Voraus.

Antwort

6
Map<String, Integer> result = 
    scores.stream() 
      .flatMap(map -> map.entrySet().stream()) 
      .collect(Collectors.toMap(Map.Entry::getKey, 
            Map.Entry::getValue, 
            Math::min)); 
5

Der minBy Downstream-Kollektor gibt Optional<Entry<String, Integer>> zurück, aber Sie benötigen einfach Integer. Sie sollten also Collectors.collectingAndThen verwenden, um einen nachgeschalteten Kollektor anzupassen. Berücksichtigen Sie auch die Verwendung der statischen Methode Map.Entry.comparingByValue().

Map<String, Integer> result = scores 
     .stream() 
     .flatMap(m -> m.entrySet().stream()) 
     .collect(Collectors.groupingBy(Map.Entry::getKey, 
      Collectors.collectingAndThen(
       Collectors.minBy(Map.Entry.comparingByValue()), 
       opt -> opt.get().getValue()))); 
+0

Danke für die Erklärung. – user5245796

0

Ein anderer Weg, ohne Ströme zu verwenden, aber mit Java 8 Funktionen:

Map<String, Integer> result = new HashMap<>(); 
scores.forEach(map -> map.forEach((k, v) -> result.merge(k, v, Integer::min))); 

Dies verwendet die Map.merge Methode den Minimalwert für einen bereits vorhandenen Schlüssel zu wählen.

Verwandte Themen