2016-01-11 15 views
11

Ho Map<A, Map<B, C>> e voglio ottenere Map<B, List<C>> da esso utilizzando Java Stream.Java Stream: ottenere i valori raggruppati per chiave interna della mappa

cerco di farlo nel modo seguente:

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) { 
    return input.values() 
      .stream() 
      .flatMap(it -> it.entrySet().stream()) 
      .collect(Collectors.groupingBy(Map.Entry::getKey)); 
} 

quello che mi aspetto:

  • flatMap dà un Stream di Map.Entry<B, C>
  • collect(Collectors.groupingBy(...)) assume la funzione che viene applicata al Map.Entry<B, C> e restituisce B, quindi raccoglie i valori di C in List<C>.

Ma non si compila, letteralmente:

metodo

non statico non è possibile fare riferimento da un contesto statico

al Map.Entry::getKey nell'ultima riga.

Qualcuno può spiegare cosa c'è che non va o qual è il modo giusto per ottenere ciò che voglio?

+0

Eventuali duplicati: http://stackoverflow.com/questions/29373026/how-to-get-all-values-from-the-inner-maps-of-a-map-using-a-common -key –

+0

@ShiladittyaChakraborty, non in realtà, sto chiedendo perché il modo previsto per farlo non funziona. Inoltre, l'attività è leggermente diversa dalla domanda a cui fai riferimento. – hotkey

risposta

11

vostro flusso è composto da Map.Entry oggetti, ma voglio che si desidera raccogliere è in realtà il valore della voce , non la voce stessa. Con il tuo codice attuale, otterresti un Map<B, List<Map.Entry<B, C>>>.

Come tale, ti manca solo una chiamata a Collectors.mapping. Questo collector mapperà l'elemento Stream con la funzione mapper assegnata e raccoglierà quel risultato nel contenitore downstream. In questo caso, il mapper è Map.Entry::getValue (quindi restituisce il valore dalla voce della mappa) e il collettore downstream si raccoglie in un List.

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) { 
    return input.values() 
      .stream() 
      .flatMap(it -> it.entrySet().stream()) 
      .collect(Collectors.groupingBy(
       Map.Entry::getKey, 
       Collectors.mapping(Map.Entry::getValue, Collectors.toList()) 
      )); 
} 
+1

Grazie, ha funzionato. Quindi, in realtà ero confuso dal messaggio di errore del compilatore. Dovrebbe essere detto dei tipi non corrispondenti, non del contesto non statico. :) – hotkey

7

La pipeline del flusso restituisce un Map<B, List<Map.Entry<B,C>>>, non un Map<B, List<C>>.

per ottenere ciò che un Map<B, List<C>>, è necessario aggiungere un mapping che mappare Map.Entry<B,C>-C:

return input.entrySet() 
     .stream() 
     .flatMap(it -> it.getValue().entrySet().stream()) 
     .collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.mapping(Map.Entry::getValue,Collectors.toList()))); 
Problemi correlati