2015-06-07 8 views
5

Chcę wziąć jedną wiadomość dziennika pojo LoggedExchange i zastosować do niej kilka transformacji. Przemiany są UnaryOperators w formie listy:Stosowanie listy funkcji do wartości ze strumieniem Java8 api

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

gdzie ConditionalTransform implementuje UnaryOperator<LoggedExchange> i moje obecne rozwiązanie jest przy użyciu zmniejszyć tak:

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

Running to równolegle nie ma sensu, ponieważ nie ma sposobu aby połączyć dwa komunikaty ((m1,m2) -> m2 jest po to, aby kompilator był szczęśliwy).

Czy istnieje lepszy sposób to zrobić (jak w jakiś sposób komponowanie wszystkich ConditionalTranforms?), A jeśli nie, czy funkcja combiner wyrzucić wyjątek lub coś, ponieważ nie mogę obsługiwać wykonania równoległego?

Według instrukcji JavaDoc większość tych operacji powinna być możliwa dzięki map i reduce, ale nie rozumiem, w jaki sposób.

+0

Czy * musisz * używać strumieni? – immibis

+1

Nie, po prostu jestem zwolniony z używania strumieni :) – vertti

+0

Nigdy nie powinieneś dostarczać kombinacji, która cicho robi coś, jeśli * wiesz *, że nie jest to właściwe. Zapewnij kombinator * rzucania *, jeśli naprawdę nie masz alternatywy. – Holger

Odpowiedz

6

Coś jak to powinno działać:

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

ten konstruuje pojedynczego UnaryOperator<LoggedExchange> która dotyczy wszystkich funkcji w transforms z kolei wywołuje go z wartości wejściowej.

Ewentualnie zawsze jest prosta wersja pętli:

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

Pierwszy przykład nie kompiluje się dla mnie. Ostatnia '.apply' nie istnieje, a operacja' reduce' nie jest legalna, IDE mówi, że 'docelowy typ konwersji lambda musi być interfejsem'. – vertti

+1

@vertti Naprawiono. Nie zauważyłem, że 'reduce' z jednym argumentem zwraca' Opcjonalnie' (co ma sens w przypadku, gdy strumień nie ma elementów). – immibis

+0

W porządku, teraz ostatni .apply działa, ale część '(LoggedExchange o) -> b.apply (a.apply (o))' nadal narzeka "docelowy typ konwersji lambda musi być interfejsem". – vertti

-2

Nie sądzę, jesteś naprawdę zmniejszenie czegokolwiek. Myślę, że zamiast tego po prostu odwzorowujesz ciąg w innym ciągu.

chciałbym napisać to:

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

I pamiętać, aby zadeklarować oryginalny jako ostateczny.

+0

To nic innego jak kosztowny noop. –

+0

Dlaczego tak jest? Przegapiłem coś? – gurghet

+0

Ponieważ przekształcasz oryginalną wartość w coś innego i nic nie robisz z efektem transformacji. –

Powiązane problemy