2015-08-20 6 views
5

Supponendo che ho il seguente elenco di mappe,Come trovare il punteggio minimo di ciascun utente da un elenco di mappe utilizzando Java 8 flusso

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

vorrei estrarre il punteggio minumum di ogni utente in un mappa utilizzando Java 8 stream con espressioni lambda. Il risultato desiderato sarebbe

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

Ho provato questo e non funziona,

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

Qualcuno potrebbe dirmi come fare?

Grazie in anticipo.

risposta

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

Il collettore a valle minBy restituisce Optional<Entry<String, Integer>>, ma è necessario semplicemente Integer. Quindi dovresti usare Collectors.collectingAndThen per adattare un collector downstream. Considerare anche l'utilizzo del metodo statico 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

Grazie per la spiegazione. – user5245796

0

Un altro modo, senza l'utilizzo di corsi d'acqua, ma con Java 8 caratteristiche:

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

Questo utilizza il metodo Map.merge per selezionare il valore minimo per una chiave già esistente.