How does apply() method work in Java?
Regarding the UnaryOperator functional interface, I have read the documentation, it says
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T>
Represents an operation on a single operand that produces a result of the same type as its operand. This is a specialization of Function for the case where the operand and result are of the same type.
This is a functional interface whose functional method is Function.apply(Object)
.
What is the functional method?
I have the following class which implements UnaryOperator interface.
public class Uppercase implements UnaryOperator<String> {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
}
In the method call,
new Stream().map(new Uppercase())
It converts whatever input stream into uppercase. My question is, does the apply()
method in Uppercase class get called automatically? ( Is it like the toString()
method is called automatically by the println()
method?)
I couldn't find any example without calling apply()
method explicitly. So please help me understand what happened here.
It converts whatever input stream into uppercase. My question is, does the apply() method in Uppercase class get called automatically?
Indeed that is the role of Stream.map()
implementation of calling apply()
on it, therefore you will never do it when Stream.map()
is invoked.
The abstract class ReferencePipeline
does that:
@SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u)); // <------ HERE
}
};
}
};
}
map()
defined in Stream is declared as :
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream.map()
expects a Function
and by passing an UnaryOperator
you provide all which is required.
I couldn't find any example without calling apply() method explicitly. So please help me understand what happened here.
Generally you don't implement directly the functional interface but you pass a lambda as that is more straight :
new Stream().map(s->s.trim().toUpperCase())....