2015-06-07 8 views
5

Desidero prendere un singolo messaggio di registro pojo LoggedExchange e applicare un gruppo di trasformazioni ad esso. Le trasformazioni sono UnaryOperators in un elenco:Applicazione di un elenco di funzioni a un valore con Java8 stream api

List<ConditionalTransform> transforms = new ArrayList<>(); 

dove ConditionalTransform implementa UnaryOperator<LoggedExchange> e la mia soluzione corrente utilizza ridurre in questo modo:

public LoggedExchange transform(LoggedExchange original) { 
    return transforms.stream().reduce(original, (o, t) -> t.apply(o), (m1, m2) -> m2); 
} 

L'esecuzione di questo in parallelo non ha senso, in quanto non v'è alcun modo per combinare due messaggi (lo (m1,m2) -> m2 è lì solo per rendere il compilatore felice).

C'è un modo migliore per farlo (come in qualche modo componendo tutti gli ConditionalTranforms?) E in caso contrario, la funzione combiner deve generare un'eccezione o qualcosa che non può supportare l'esecuzione parallela?

Il JavaDoc afferma che la maggior parte di queste operazioni dovrebbe essere possibile fare con map e reduce ma non vedo come.

+0

Sei * richiesto * per utilizzare i flussi? – immibis

+1

No, sono solo _tempted_ per usare gli stream :) – vertti

+0

Non dovresti mai fornire un combinatore che faccia silenziosamente qualcosa, se * sai * che questo non è appropriato. Fornisci un combinatore * di lancio * se non hai davvero alternative. – Holger

risposta

6

Qualcosa del genere dovrebbe funzionare:

public LoggedExchange transform(LoggedExchange original) { 
    return transforms.stream().reduce(UnaryOperator.identity(), (a, b) -> ((LoggedExchange o) -> b.apply(a.apply(o)))).apply(original); 
} 

Questo costruisce una singola UnaryOperator<LoggedExchange> che applica tutte le funzioni in transforms a sua volta, poi chiama con il valore di ingresso.

In alternativa, c'è sempre la semplice versione looping:

public LoggedExchange transform(LoggedExchange value) { 
    for(UnaryOperator<LoggedExchange> transform : transforms) 
     value = transform.apply(value); 
    return value; 
} 
+0

Il primo esempio non viene compilato per me. L'ultimo '.apply' non esiste e l'operazione' reduce' non è legale, dice IDE 'il tipo di destinazione della conversione lambda deve essere un'interfaccia'. – vertti

+1

@vertti Risolto. Non ho notato che 'reduce' con un argomento restituisce un' Optional' (che ha senso nel caso in cui il flusso non abbia elementi). – immibis

+0

OK, ora l'ultimo .apply funziona ma il '(LoggedExchange o) -> b.apply (a.apply (o))' parte lamenta ancora "il tipo di destinazione della conversione lambda deve essere un'interfaccia". – vertti

-2

Non credo che si sta davvero riducendo nulla. Penso che tu stia semplicemente mappando una stringa in un'altra stringa.

avrei scritto questo:

trasforms 
    .forEach(transformation -> transformation.apply(original)); 

E ricorda di dichiarare originale come finale.

+0

Questo non è altro che un costoso noop. –

+0

Perché è quello? Ho dimenticato qualcosa? – gurghet

+0

Perché stai trasformando un valore originale in qualcos'altro e non fai nulla con il risultato della trasformazione. –

Problemi correlati