Home Java Functional Interfaces in Java

Functional Interfaces in Java

Published: Last Updated on 0 comment

Hey! tea lovers. This post is about Java’s functional interfaces. We will talk about the basic ones briefly. These functional interfaces are used by Stream API heavily, so knowing them will give you a huge advantage. Not just streams you can use it anywhere.


I would be happy to connect with you guys on social media. It’s @coderstea on TwitterLinkedinFacebook, Instagram, and YouTube.

Please Subscribe to the newsletter to know about the latest posts from CodersTea.


Prerequisites for Functional Interfaces

Not much, Just make sure the concept of functional interfaces and lambdas are clear. You can find the code on GitHub here or the full project here. And yes fill your cup of tea to sip and learn with me.

Functional Interfaces package: java.util.function

The functional interfaces we will be discussing during your tea break will be java.util.function. This package contains Java’s general-purpose functional interface to be used by coders like us. This helps us to save time by not writing it repeatedly. It has many functional interfaces (you probably won’t be needing that many in your code) but we are going to see the most common and useful functional interfaces. We will be comparing it to the normal method or function for better comprehension

Consumer <T>

As the name implies Consumer consumes the inputs. It doesn’t return anything when called. It is similar to the function with the void return type. This functional interface has 2 methods one being the void accept(T t) to trigger it and the other is the default method andThen(Consumer<T>) which lets you chain multiple Consumers. You can call multiple Consumers  andThen(consumer1).andThen(consumer2)..... and call accept(t) function to terminate the chain. All Consumers in this chaining will use the same input given via accept().

Consumer<Integer> printAgeConsumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer age) {
                System.out.println("Age is " + age);
            }
        };
//call the method
printAgeConsumer.accept(23);// Age is 23
//using lambda
Consumer<Integer> printAgeWithLamda = (age) -> System.out.println("Lamdda : age is " + age);
//will work similar as printAgeConsumer
printAgeWithLamda.accept(223);//Lamda : age is 223
//chaining with andThen(Consumer)
printAgeConsumer //1st
        .andThen(printAgeWithLamda)//2nd
        .andThen(age -> System.out.println("How old is he ? " + age))//3rd
        .accept(23);//this value will be given to each consumerCode language: JavaScript (javascript)

Predicate <T>

The Predicate is used for boolean values. It tests the given value and returns a boolean by calling test(T t). Then again like Consumer, you can use chaining using and(anotherPredicate). And calling test(T) in the end, it will complete the chain. Similar to Consumers they use the same input throughout the chain. It returns true only if all the predicates return true else it returns false.

Predicate<Integer> isEven = new Predicate<Integer>() {
            @Override
            public boolean test(Integer number) {
                return number % 2 == 0;
            }
        };
boolean is23Even = isEven.test(23);//false
//using lambda
Predicate<Integer> isEvenlambda = (number) -> number % 2 == 0;
boolean is46Even = isEvenlambda.test(46);//true
//chaining with and()
//returns true only of all the predicated returns true else false
isEven // 1st - number should be even
        .and(n -> n < 10)//2nd -number should be less than 10
        .and(n -> n > 5) // 3rd should be greater than 5
        .test(6); // this nu,ber will be used in chain
// returns true after completionCode language: PHP (php)

Function <T, R>

Yes, that’s the name. Unlike preceding interfaces, Function has two generic parameters. The first parameter is for the input type and the second one is for the return type. Essentially Function is used for transforming the given value into the desired one. Functions use apply(T t) for its functions and andThen(anotherFuntion) for chaining. But dissimilar to Consumer and Predicate this chaining does not use the same value for all the Functions instead, they use the result of the preceding Function. But keep in mind that, the subsequent Function has the input type equivalent to the current Function’s return type.

Function<Integer, Integer> doubleTheNumber = new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer number) {
                return number * 2;
            }
        };
int doubleTheNumber2 = doubleTheNumber.apply(2);//4
//using lambda
Function<Integer, Integer> subtract2 = (number) -> number - 2;
int subtract2From4 = doubleTheNumber.apply(4);
System.out.println(subtract2From4);
//chaining with andThen()
//Unlike Predicate and Consumer which uses the same value to all the nodes,
//Function uses the result of previous Function
doubleTheNumber // 1st will double the number
        .andThen(subtract2) // 2nd will subtract 2 from doubled number
        .andThen(doubleTheNumber) // 3rd subtracted result will be doubled
        .apply(4); // (((4 * 2) - 2) * 2) = 12Code language: PHP (php)

BiFunction <T, U, V>

BiFunction is similar Function but it accepts two input parameters as opposed to Function which takes only one input. It has apply(T t, U u)  the function of triggering it. Chaining within BiFucntion is a little different. It uses Function as a parameter the andThen as andThen(Function<V v, E e>) ( since methods don’t have two return values).

BiFunction<Integer, Integer, Integer> areaOfRectangle = new BiFunction<Integer, Integer, Integer>() {
    @Override
    public Integer apply(Integer length, Integer breadth) {
        return length * breadth;
    }
};
areaOfRectangle.apply(2, 2);//4
BiFunction<Integer, Integer, String> areaWitMessage = (lengh, breadth) -> "Area is " + lengh * breadth;
areaWitMessage.apply(4, 3);// Area is 12
//chaining
areaOfRectangle // 1st area will be calculated
        .andThen(area -> area * 3) // 2nd calculated area will be multiplied by 3 as height
        .apply(2, 3);// 2 * 3 * 3 = 18Code language: JavaScript (javascript)

Supplier < T >

Till now we have talked about the interfaces which take input parameters. Supplier, on the other hand, does not demand any arguments, it just produces one by calling get(). Completely different than selfish Consumer, a taker, Supplire is a giver. It is like a method that produces values without input, like toString() or hashCode(). We can’t use chaining in this since it does not take any input parameters.

Supplier<Double> randomSupplier = new Supplier<Double>() {
    @Override
    public Double get() {
        return Math.random();
    }
};
double randomNumber = randomSupplier.get();
System.out.println(randomNumber);
//lambda
Supplier<String> codersTeaUrl = () -> "https://coderstea.in";
System.out.println(codersTeaUrl.get());Code language: JavaScript (javascript)

There are more Functional Interfaces

The ones we talked about are popular and are used in Stream API heavily. But there are more functional interfaces. They are similar to these functions in one or another way. Don’t worry, we don’t have to understand every functional interface in java. If you understood the above-mentioned interfaces, it’s more than enough.

Still just to name a few, the following table is obtained from the Java doc. you can find it here

InterfaceDescription
BiConsumer<T,U>Represents an operation that accepts two input arguments and returns no result.
BiFunction<T,U,R>Represents a function that accepts two arguments and produces a result.
BinaryOperator<T>Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
BiPredicate<T,U>Represents a predicate (boolean-valued function) of two arguments.
BooleanSupplierRepresents a supplier of boolean-valued results.
Consumer<T>Represents an operation that accepts a single input argument and returns no result.
DoubleBinaryOperatorRepresents an operation on two double-valued operands and producing a double-valued result.
More functional interfaces

Conclusion

That’s it for the post. In this post, we learned about the inbuilt functional interfaces in Java. These functional interfaces are the backbone of the Stream API. I have written a post on the same topic titled “Stream API: The Hero Without A Cape“. You can find the code on GitHub here or the full project here. See you in the next post.

See you in the next post. HAKUNA MATATA!!!


I would be happy to connect with you guys on social media. It’s @coderstea on TwitterLinkedinFacebook, Instagram, and YouTube.

Please Subscribe to the newsletter to know about the latest posts from CodersTea.


Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Ads
Ads
Ads

@2023 All Right Reserved. Designed and Developed by CodersTea

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More