Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying a list of functions to a value with Java8 stream api

I want a take a single log message pojo LoggedExchange and apply a bunch of transformations to it. The transformations are UnaryOperators in a list:

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

where ConditionalTransform implements UnaryOperator<LoggedExchange> and my current solution is using reduce like this:

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

Running this in parallel does not make sense, as there is no way to do the combining of two messages (the (m1,m2) -> m2 is there just to make the compiler happy).

Is there a better way to do this (like somehow composing all the ConditionalTranforms?) and if not, should the combiner function throw an exception or something as I can't support parallel execution?

The JavaDoc states that most of these operations should be possible to do with map and reduce but I don't see how.

like image 958
vertti Avatar asked Jun 07 '15 08:06

vertti


1 Answers

Something like this should work:

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

This constructs a single UnaryOperator<LoggedExchange> which applies all of the functions in transforms in turn, then calls it with the input value.

Alternatively, there's always the straightforward looping version:

public LoggedExchange transform(LoggedExchange value) {
    for(UnaryOperator<LoggedExchange> transform : transforms)
        value = transform.apply(value);
    return value;
}
like image 66
user253751 Avatar answered Oct 14 '22 16:10

user253751