Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping an object using a List<UnaryOperator<...>>

I have a List<UnaryOperator<String>> and need to map/transform a String by passing it through the list of operators. I have the following functional Java 11 code:

UnaryOperator<String> addA = (startString) -> startString + "a";
UnaryOperator<String> addB = (startString) -> startString + "b";
UnaryOperator<String> addc = (startString) -> startString + "c";
List<UnaryOperator<String>> operators = List.of(addA, addB, addc);
String concatenatedString =
    operators
        .stream()
        .reduce(
            "", // identity
            (value, op) -> op.apply(value), // accumulator
            (value1, value2) -> value1.concat(value2) // combiner
        );
System.out.println(concatenatedString); // prints "abc" as expected.

The concern I have is the string concatenation is expressed in 2 places. First in each of the UnaryOperators and second in the combiner argument. Makes me wonder if there is a better way to do this?

like image 714
Ram Avatar asked Sep 25 '26 14:09

Ram


1 Answers

You can use the advantage that UnaryUperator<T> extends Function<T, T> and chain multiple calls of Function::andThen to get a composed UnaryOperator<String> of all within the list:

UnaryOperator<String> mergedUnaryOperators = operators.stream()
            .reduce((l, r) -> (string) -> l.andThen(r).apply(string))
            .orElseGet(UnaryOperator::identity);

String output = mergedUnaryOperators.apply("");      // results in "abc"

To have a clearer picture how does it work, this is called inside the reduce method:

new BinaryOperator<UnaryOperator<String>>() {
  @Override
  public UnaryOperator<String> apply(UnaryOperator<String> l, UnaryOperator<String> r) {
     return string -> l.andThen(r).apply(string);
  }
}
like image 128
Nikolas Charalambidis Avatar answered Sep 28 '26 05:09

Nikolas Charalambidis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!