Such as in .Net, which provides several implementations of the Action
delegate (equivalent to Java Consumer
functional interface) with different number and type of arguments, I was expecting that Java 8 provides some way of specifying a Consumer
with more than one argument of different types.
I know that in Java we cannot define different types with the same name that just differ in the generic type parameters, but there would be nice fluent alternatives to provide a multi-argument Consumer
.
Is there any easy way to do it, which does not require defining a new functional interface?
For 3 and more arguments you could use curried(http://en.wikipedia.org/wiki/Currying) functions with last consumer:
Function<Double, Function<Integer, Consumer<String>>> f = d -> i -> s -> {
System.out.println("" + d+ ";" + i+ ";" + s);
};
f.apply(1.0).apply(2).accept("s");
Output is:
1.0;2;s
It's enough to have a function of one argument to express function of any number of arguments: https://en.wikipedia.org/wiki/Currying#Lambda_calculi
By default you're limited with only java.util.function.Consumer
and java.util.function.BiConsumer
. They are sufficient for current java streaming API. But you can create your own functional interfaces that will receive as many arguments as you like and use it in your own custom APIs.
It's pretty easy to define Functional Interfaces for yourself. In the project I am currently working on, I have found several occasions where passing a method as an argument has allowed me to keep my code nice and DRY. Here are some functional interfaces I've defined:
@FunctionalInterface
public interface CheckedVoidFunction {
void apply() throws Exception;
}
@FunctionalInterface
public interface VoidFunction {
void apply();
}
@FunctionalInterface
public interface SetCategoryMethod {
void accept(ObservableList<IRegionWithText> list, Document document, String pattern);
}
Here are a method that accepts these kinds of arguments:
private void loadAnnotations(String annotationType, VoidFunction afterLoadFunction, List<Path> documentPaths) {
And here is where I call these methods with different methods as arguments:
loadAnnotations(DocumentReader.REDACTION_ANNOTATION_TYPE, this::afterLoadRedactions, documentPaths);
loadAnnotations(DocumentReader.HIGHLIGHT_ANNOTATION_TYPE, this::afterLoadHighlights, documentPaths);
There may be better ways to do this, but I thought I'd share what has been useful for me.
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