Many lambdas for the Function
interface take the form
t -> {
// do something to t
return t;
}
I do this so often that I have written a method for it like this.
static <T> Function<T, T> consumeThenReturn(Consumer<T> consumer) {
return t -> {
consumer.accept(t);
return t;
};
}
This enables me to do really nice things like this:
IntStream.rangeClosed('A', 'Z')
.mapToObj(a -> (char) a)
.collect(Collectors.collectingAndThen(Collectors.toList(), consumeThenReturn(Collections::shuffle)))
.forEach(System.out::print);
Is there another way to do conversions like this without relying on my own method? Is there anything in the new APIs I have missed that makes my method redundant?
Interface Consumer<T> Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects. This is a functional interface whose functional method is accept(Object) .
The difference between these is that the predicate uses the parameter to make some decision and return a boolean whereas Consumer uses the parameter to change some of its value.
There are many potentially useful methods that could be added to the Function
, Consumer
and Supplier
interfaces. You give a good example (converting a Consumer
to a Function
) but there are many other potential conversions or utilities that could be added. For example, using a Function
as Consumer
(by ignoring the return value) or as a Supplier
(by providing an input value). Or converting a BiFunction
to a Function
by supplying either value. All of these can, of course, be done manually in code or provided via utility functions as you've shown but it would arguably be valuable to have standardised mechanisms in the API, as exist in many other languages.
It is speculation on my part, but I would guess this reflects the language designers' desire to leave the API as clean as possible. However I'm intrigued by the contrast (as an example) to the very rich set of Comparator
utilities provided by the language to reverse orders, compare by several criteria, deal with null values etc. These also could easily have been left to the user but have been supplied by the API. I'd be interested to hear from one of the language designers why the approaches to these interfaces seems so inconsistent.
Apache commons collections 4.x has what you're looking for, I think. Its equivalents for Function
and Consumer
are Transformer
and Closure
, respectively, and it provides a way to compose them using ClosureTransformer
It is trivial to convert between equivalent functional types by invoking the SAM of one and assigning it to the other. Putting it all together, you can end up with a Java 8 Function
in this manner:
Consumer<String> c = System.out::println;
Function<String,String> f = ClosureTransformer.closureTransformer(c::accept)::transform;
c::accept
converts the Java 8 Consumer
to an equivalent Apache Commons 4 Closure
, and the final ::transform
converts the Apache Commons 4 Transformer
to an equivalent Java 8 Function
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With