Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Streams in Java, can't figure this code out

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))?

like image 641
masterofdisaster Avatar asked Nov 26 '17 11:11

masterofdisaster


People also ask

How do I know if my stream is not empty?

You have to consume the stream to find out if it's empty. That's the point of Stream's semantics (laziness). To check that the stream is not empty you have to attempt to consume at least one element. At that point the stream has lost its "virginity" and cannot be consumed again from the start.

Is Java stream blocking?

Java IO's various streams are blocking. That means, that when a thread invokes a read() or write() , that thread is blocked until there is some data to read, or the data is fully written. The thread can do nothing else in the meantime.

What is stream () method in Java?

A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. The features of Java stream are – A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.


2 Answers

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.

like image 76
Eran Avatar answered Oct 12 '22 01:10

Eran


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.

like image 43
Eugene Avatar answered Oct 12 '22 01:10

Eugene