4 available functional interfaces and examples with Stream API
- Tram Ho
As the previous two articles have introduced, one of the conditions of functional programming is the ability to pass one function into another. Java has done this by declaring the functional interface and the corresponding pass implementation.
However, if you have to define a new functional interface each time, it’s too verbose. With the common “shape” methods, Java has predefined quite a few functional interfaces to save you the need to rewrite. 4 basic ones include Consumer
, Function
, Predicate
and Supplier
, You must have heard it before, let’s find out more through this article.
1. Four basic functional interfaces
Actually, when learning about this functional interface, just remember its structure. Eg Consumer<T>
, What parameters to accept, what data type to return.
Besides, most of these functional interfaces use generics. Nor does it need to remember what generics param is, it can be deduced from the meaning.
1.1. Consumer<T>
Get a param of type T
, returns nothing. In simple words, they only like to receive but do not give away.
1 2 3 | <span class="token class-name">Consumer</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Integer</span><span class="token punctuation">></span></span> print <span class="token operator">=</span> num <span class="token operator">-></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>num<span class="token punctuation">)</span><span class="token punctuation">;</span> print<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 3</span> |
Usually found in functions that handle elements, such as getting an element and doing something.
1.2. Function<T, R>
Get a parameter T
, returns a value of type R
.
1 2 3 | <span class="token class-name">Function</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Integer</span><span class="token punctuation">></span></span> getLength <span class="token operator">=</span> str <span class="token operator">-></span> str<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> getLength<span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token string">"John Doe"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 3</span> |
Used to transform one value into another (map 1 with 1).
1.3. Predicate<T>
Get a parameter T
and return boolean.
1 2 3 | <span class="token class-name">Predicate</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Integer</span><span class="token punctuation">></span></span> checkAge <span class="token operator">=</span> age <span class="token operator">-></span> age <span class="token operator">></span> <span class="token number">18</span><span class="token punctuation">;</span> checkAge<span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span> |
Used to check if the element satisfies the condition or not.
1.4. Supplier<T>
This man has blood type O. He only knows how to give, but he doesn’t need to receive it in return.
This functional interface takes no parameters, but returns a value.
1 2 3 | <span class="token class-name">Supplier</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Double</span><span class="token punctuation">></span></span> generate <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span> generate<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Số random nào đó</span> |
Usually used to generate infinite streams.
2. Example of each type in Stream API
The above 4 functional interfaces are quite basic, but you will wonder where is it used? The answer is used in Stream API operations.
Here I will explain basically how the stream works:
- Gets a stream (like a continuous stream of elements) from an array or collection
- The elements of the stream will go through many operations (like that filter).
- Each operation will transform each element, depending on the type of operation (map, filter, …)
- The final result will be processed
Example code for easy understanding.
1 2 3 4 5 | <span class="token class-name">List</span><span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Lấy ra stream từ List</span> <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>num <span class="token operator">-></span> num <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">// Mỗi phần tử sẽ được nhân đôi</span> <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>num <span class="token operator">-></span> num <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token comment">// Chỉ giữ lại các phần tử nhỏ hơn 10</span> <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>num <span class="token operator">-></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>num<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// In ra các phần tử còn lại</span> |
Here map()
, filter()
and forEach()
are stream operations. Each type will perform a different function, and it uses the corresponding functional interface types:
map()
to transform the element 1-1, so it usesFunction<T, R>
filter()
to filter out matching elements, it usesPredicate<T>
forEach()
just use print out, don’t return anything, so it usesConsumer<T>
Usually people write lambda form for short, and always write in operation. If you want you can still separate, like on the example in part 1.
Oh how many
apply()
,test()
,… inside functional interface, where to do it?
Those methods will be implicitly implemented by the Stream API. You just need to put the lambda into the operation, the code inside of that operation will know and call the corresponding method inside.
Okay the post is quite long, I will stop here. In the next post we will continue to come to other available functional interfaces, with more “advanced” forms.