Composing Consumers – Functional-Style Programming

Composing Consumers

The method andThen() can be used to chain together consumers to compose compound consumers. The three consumers used earlier to resize, reverse, and print a StringBuilder can be chained together as seen here:

Click here to view code image

resizeSB.andThen(reverseSB)
    .andThen(printSB).accept(new StringBuilder(“Banana”)); // StringBuilder: anaB

The constituent consumers are executed one after the other from left to right. Note that the reference to the StringBuilder instance passed to the accept() method is also passed to each constituent consumer.

Click here to view code image

default Consumer<T> andThen(Consumer<? super T> after)

Returns a composed Consumer that evaluates this operation first followed by the specified after operation.

Any exception thrown during the evaluation of either operation aborts the evaluation of the composed operation and the exception is conveyed to the caller.

Primitive Type Specializations of Consumer<T>

From Table 13.6, we see that the non-generic functional interfaces IntConsumer, LongConsumer, and DoubleConsumer define the functional method accept() that takes an int, a long, or a double value as an argument, respectively, but does not return a value (void). The primitive type versions avoid the overhead of boxing and unboxing of primitive values. They are not subinterfaces of the Consumer<T> interface, and they all provide the andThen() method to compose compound primitive type consumers.

The two IntConsumers below print the square root and the square of their argument, respectively. They are chained by the andThen() method that requires an IntConsumer.

Click here to view code image

IntConsumer sqrt = i -> System.out.printf(“%.2f%n”, Math.sqrt(i));
IntConsumer sqr = i -> System.out.printf(“%d%n”, i * i);
sqrt.andThen(sqr).accept(15);    // 3.87
                                 // 225

Two-Arity Specialization of Consumer<T>: BiConsumer<T, U>

The BiConsumer<T, U> interface is a two-arity specialization of the Consumer<T> interface. From Table 13.6, we see that its functional method accept() has the type (T, U) -> void—that is, it takes two arguments of type T and type U, and does not return a value (void). The BiConsumer<T, U> interface provides the andThen() method to create compound two-arity consumers.

The following code illustrates defining and using two-arity consumers.

Click here to view code image

BiConsumer<String, Double> formatPrinter
    = (format, obj) -> System.out.printf(format, obj);
formatPrinter.accept(“Math.PI:|%10.3f|%n”, Math.PI); // Math.PI:|     3.142|

The java.util.Map.forEach() method requires a two-arity consumer that is applied to each entry (key, value) in the map—that is, the method call biconsumer.accept(key, value) is executed for each entry in the map. The two-arity consumer below formats and prints all entries in the map given by the reference strLenMap. The key in this map is of type String and the value is of type Integer— that is, HashMap<String, Integer>. The value is the length of the key string.

Click here to view code image

// Map entries (default format): {Java=4, Bob=3, Otto=4, HannaH=6, Alya=4, ADA=3}
strLenMap.forEach((key, value) -> System.out.printf(“(%s:%d) “, key, value));
// (Java:4) (Bob:3) (Otto:4) (HannaH:6) (Alya:4) (ADA:3)

Leave a Comment