2014-09-15 12 views
8

Ho un flusso di articoli non ordinati e un flusso di comparatori. Voglio applicare tutti i comparatori sullo stream usando "thenComparing" (Multisort) Esiste un modo più elegante del seguente codice per ottenere questo?Come fare catena e applicare un flusso di comparatori?

Stream unsorted = ...; 
Stream<Comparator> comparators = ...; 

Comparator compareFunc = comparators.reduce(null, (a, b) -> { 
     if(a == null) { 
      return b; 
     }else { 
      return a.thenComparing(b); 
     } 

    }); 

Stream result = unsorted.sorted(compareFunc); 
+0

Vorrei evitare il parametro null di riduzione e l'istruzione if (a == null) – jack

+2

Sarebbe probabilmente leggermente più pulito se si utilizza un comparatore di base che restituisce sempre 0 invece di 'null'. Ciò rimuoverebbe il null e il ramo. –

+2

@mark sì che semplifica il codice compareFunc = comparators.reduce ((a, b) -> 0, (a, b) -> a.thenComparing (b)); thanxs – jack

risposta

6

Non utilizzare un valore di identità per s. Se il flusso comparators è vuoto (cioè non contiene alcuna Comparator) non si dovrebbe sorta:

Stream result=comparators.reduce(Comparator::thenComparing) 
      .map(unsorted::sorted).orElse(unsorted); 

Si noti che se il flusso comparators contiene un solo Comparator, che Comparator sarà il risultato della riduzione.


Il riferimento metodo passato a Optional.map potrebbe aver bisogno di una certa esperienza per abituarsi ad esso. Quindi, forse vale la pena utilizzare la sintassi lambda più prolisso per mostrare ciò che sta succedendo lì:

Stream<String> result=comparators.reduce(Comparator::thenComparing) 
    .map((comparator) -> unsorted.sorted(comparator)).orElse(unsorted); 

Questa è una questione di stile di programmazione o di preferenze personali e potrebbe cambiare nel tempo.

+0

thanxs sembra così bello – jack

4

Utilizzando suggerimento Mark Peters' e mescolandolo con un riferimento metodo, si potrebbe scrivere il confronto in questo modo:

Comparator compareFunc = comparators.reduce((a, b) -> 0, Comparator::thenComparing); 

o rubare un po 'da Holger invece:

Optional<Comparator> compareFunc = comparators.reduce(Comparator::thenComparing); 
Stream<?> result = compareFunc.isPresent() ? result.sorted(compareFunc.get()) 
              : unsorted; 
+2

@Holger Ho rubato un po 'della tua idea - trovo la sintassi invertita della tua risposta meno chiara per essere onesta. – assylias

+1

Bene, preferisco dire a 'Optional' cosa fare usando' isPresent() '. Questo è più vicino a quello che fai con 'Stream's contro iterazione esterna. Ma, ovviamente, l'operazione esterna esprime di più (è più verbosa) cosa sta succedendo ... – Holger

Problemi correlati