The Function Interface is introduced in Java 8, to implement functional programming in Java. It represents a function that takes in one argument and produces a result. It's easy to practise and read, but I am still trying to understand the benefit of it other than just making it look cool. For example,
Function<Integer, Double> half = a -> a / 2.0;
Function<Double, Double> triple = b -> b * 3;
double result = half.andThen(triple).apply(8);
can just be converted as a standard method like
private Double half(int a) {
return a / 2.0;
}
private Double triple (int b) {
return b * 3;
}
double result = triple(half(8));
So what's the benefit of using Function? As it refers to functional programming, what exactly is functional programming in Java and benefit it could bring? Would it benefit the way like:
Stream
?Basically, I'm curious to know, in what circumstances would we prefer using function rather than normal method? Is there any use case that's unable or difficult to use, or converted with a normal method?
A function in JavaScript is a statement that performs a task or calculates a value, takes in an input, and returns an output as a result of the relationship between the input. A method is a property of an object that contains a function definition. Methods are functions stored as object properties.
The basic objective of this style of programming is to make code more concise, less complex, more predictable, and easier to test compared to the legacy style of coding. Functional programming deals with certain key concepts such as pure function, immutable state, assignment-less programming etc.
Functional interfaces are included in Java SE 8 with Lambda expressions and Method references in order to make code more readable, clean, and straightforward. Functional interfaces are interfaces that ensure that they include precisely only one abstract method.
One usage of Function
is in Streams. Everyone uses map
method these days, I believe:
This map
method accepts the Function
as a parameter. This allows writing a pretty elegant code - something that could not be achieved before Java 8:
Stream.of("a", "b", "c")
.map(s -> s.toUpperCase())
.collect(Collectors.toList());
// List of A, B, C
Now its true that there are method references and functional interfaces (one of which is Function
of course), this lets you using method reference to rewrite the above example as:
Stream.of("a", "b", "c")
.map(String::toUpperCase)
.collect(Collectors.toList())
... but that's only a syntactic sugar - map
still accepts the Function
as a parameter of course.
Another example that uses Function
from Java itself is StackWalker
:
Here is an example:
List<StackFrame> frames = StackWalker.getInstance().walk(s ->
s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
.limit(10)
.collect(Collectors.toList()));
}
Note the call to walk
method - it accepts a function as a parameter.
So bottom line, it's just yet another tool that can help the programmer to express his/her intentions. Use it wisely wherever appropriate.
Suppose I want to write an applyTwice
function:
double applyTwice(double x, Function<Double, Double> f) {
return f.apply(f.apply(x));
}
This needs the function be represented as an object.
Functions are useful when you want to put some structure around arbitrary code supplied by the caller.
One example I had to use just a few days ago at my workplace is when I wanted to lazily compute a message, depending on a condition. For example imagine a logger
usage like this:
logger.debug("my-heavy-computed-message-here");
Now imagine that the computation of "my-heavy-computed-message-here"
is really just that - it is heavy to compute; but you only want to present it if the DEBUG
logger is enabled. What people usually do is:
if(logger.isDebugEnabled()) {
logger.debug("my-heavy-computed-message-here");
}
This is ugly. Instead, we have some code in place that takes a Function
(or Supplier
) as input:
logger.debug(Function<SomeObject, String> function)
Internally in our logger implementation we call function::apply
(thus computing that expensive String) only as needed (or in a 'lazy' fashion).
In Java it's usually called "pure functions", which are defined alike:
The execution of the function has no side effects.
The return value of the function depends only on the input parameters passed to the function.
Anything else should be an object's method.
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