I've found the following code snippet:
Function<Integer, Predicate<Integer>> smallerThan = x -> y -> y < x;
List<Integer> l = Arrays.asList(5, 6, 7, 23, 4, 5645,
6, 1223, 44453, 60182, 2836, 23993, 1);
List<Integer> list2 = l.stream()
.filter(smallerThan.apply(l.get(0)))
.collect(Collectors.toList());
System.out.println(list2);
As output I receive:
[4, 1]
How does the smallerThan
function in this example work, considering that we only pass one parameter smallerThan.apply(l.get(0))
?
smallerThan
is a Function
that accepts a single Integer
and returns a Predicate<Integer>
(a Predicate<Integer>
is a function that accepts a single Integer
and returns a boolean
).
smallerThan.apply(l.get(0))
returns a Predicate<Integer>
that looks like this:
y -> y < l.get(0)
i.e. it returns true
if the input passed to it is smaller than l.get(0)
.
When you pass that Predicate
to filter
, your Stream
pipeline keeps only the elements smaller than l.get(0)
.
Your pipeline can be re-written as:
List<Integer> list2 = l.stream()
.filter(y -> y < l.get(0))
.collect(Collectors.toList());
Since l.get(0)
is 5
, your pipeline returns all the elements of the original list smaller than 5
.
That is called "currying" and it was possible before Java 8 too via anonymous classes for example, but it was much more verbose. Ultimately, it's a Function
that returns a Function
and while not that spread in Java (yet), in other functional languages it is used quite heavily.
The function smallerThan
accepts a number and returns a Predicate
object, in which case we apply this predicate to every element of the stream.
So, l.get(0)
will retrieve the first value of the list l
which is (5)
, we then pass it to the smallerThan
function and this function returns a predicate with the criteria y -> y < x;
which reads as "given a number, return true if it is less than 5" hence output is [4, 1]