2015-02-18 10 views
5

Attualmente ho la seguente situazione:attributo Somma di oggetto con flusso API

Ho un oggetto Report che può contenere più Query oggetti. Gli oggetti Query hanno proprietà: Optional<Filter> comparisonFilter, Optional<String> filterChoice e int queryOutput.

Non tutte le query hanno un filtro di confronto, quindi per prima cosa lo controllo. Quindi, mi assicuro di ottenere le query per un filtro particolare (che non è il problema qui, quindi non discuterò in dettaglio). Ogni filtro ha alcune scelte, di cui il numero di scelte è variabile.

Ecco un esempio di ingresso (questi Query oggetti hanno tutti lo stesso comparisonFilter):

Query 1 -- Choice: 'First' -- Output: 10 
Query 1 -- Choice: 'First' -- Output: 5 
Query 1 -- Choice: 'Second' -- Output: 25 
Query 1 -- Choice: 'Third' -- Output: 10 

Ora, vorrei riassumere le uscite di query per ogni scelta unica. Al momento ho questo codice:

report 
.getQueries() 
.stream() 
.filter(q -> q.getComparisonFilter().isPresent()) 
.filter(q -> q.getComparisonFilter().get().equals(view.getFilter().get())) 
.forEach(query -> { 

    //Sum the query outputs per choice 

}); 

potrei farlo creando un Map<String, Integer>, in cui la chiave è la scelta e il valore è l'ingresso query. Ma poi avrei bisogno di passare di nuovo dallo Map per usare il valore per qualcosa (che non è importante qui).

L'output dovrebbe essere simile a questo:

Choice: 'First' -- Summed Output: 15 
Choice: 'Second' -- Summed Output: 25 
Choice: 'Third' -- Summed Output: 10 

ma vorrei utilizzare questo 'uscita sommata' direttamente in una forEach sul torrente, ma se questo non è possibile o pratico più, sto bene con quello.

Mi piacerebbe farlo 'Java 8'-way, ma non riesco a capire come.

Quindi la mia domanda è: È possibile farlo più breve con la nuova API Stream?

Nota: se qualcuno ha qualche idea su come rendere questa domanda più generale (forse un titolo migliore e alcune generalizzazioni), fatemelo sapere!

+1

Sembra come se si dispone di questo problema: http: //www.leveluplunch.com/java/examples/java-util-stream-groupingBy-example/ –

+0

Grazie per il tuo commento @LutzHorn, è un link molto utile. Ottengo il metodo 'groupingBy', e quindi potrei trasmettere il' keySet', ma è anche possibile sommare il 'queryInput' per ogni scelta all'interno dello stream? Forse è possibile una riduzione? – bashoogzaad

+2

@bashoogzaad Non sono sicuro di ottenere ciò che vuoi fare; in particolare l'uso di 'Optional filterChoice'. Vuoi sommare le query dal valore in questo facoltativo o dai valori nell'opzionale che contiene il filtro? È possibile avere un esempio di input/output? –

risposta

5

Se ho capito bene, stai davvero cercando uno groupingBy e quindi devi raggruppare i valori sommando la loro proprietà int.

Il groupingBy vi darà un Map<String, List<Query>> ma poi il collettore a valle (Collectors.summingInt in questo caso) si sommare tutti i valori int delle Query casi nella lista, con un conseguente Map<String, Integer>.

import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.summingInt; 
... 

Map<String, Integer> map = 
    report.getQueries() 
      .stream() 
      .filter(q -> q.getComparisonFilter().isPresent()) 
      .filter(q -> q.getComparisonFilter().get().equals(view.getFilter().get())) 
      .collect(groupingBy(q -> q.filterChoice.get(), summingInt(q -> q.queryOutput))); 

noti che si dovrebbe verificare se il filterChoice opzionale non è vuoto (forse aggiungere un'altra clausola filter?). Puoi vedere questo piccolo gist per una demo semplice e semplificata per illustrare il principio.

anche la classe Optional fornire un'implementazione sensibile equals quindi la clausola di filtro potrebbe assomiglia a questo:

.filter(q -> q.getComparisonFilter().equals(view.getFilter())) 
+2

Stavo per rispondere lo stesso. Solo 20 secondi dietro di te ... –

+0

Grazie per la tua grande risposta! Sembra funzionare in sostanza, ma ottengo un errore che 'Map ' non può essere lanciato su 'Map '. Penso che abbia qualcosa a che fare con il mio codice, ma filterChoice è solo un 'Opzionale '. Cercherò di capirlo e accetterò la tua risposta. – bashoogzaad

+2

@bashoogzaad Compilate con Eclipse o Javac? Il compilatore di Eclipse ha ancora alcuni problemi con l'inferenza di tipo (e con alcune caratteristiche di Java 8 in generale). Prova a compilarlo con javac. Se non viene compilato; o hai fatto un errore o avresti dovuto aiutare il compilatore fornendo il tipo ;-) –

Problemi correlati