Java 8 Lambdas, Functional Interface & "static" and "default" methods

  • 4.5/5
  • 4975
  • Jul 20, 2024

Java 8: "static" and "default" methods in interface

All "interface" methods are implicitly "public" and "abstract," unless declared as "static" or "default."

As of Java 8, it is now possible to inherit concrete methods (static and default) from an interface.

The implementation class is not required to implement "static" or "default" methods.

Optionally, an implementation class can inherit "default" interface methods but not "static" interface methods.

Functional Interfaces

A functional interface is an interface that contains only one abstract method.

In this SAM (single abstract method) rule, "default," "static," and methods inherited from "Object" class do not count.

In the example above, the "int hashCode()" method is overridden from the "Object" class.

Java 8 lambdas

A "Lambda" expression is an instance of a class that implements a functional interface.

Lambdas resemble "methods," but they are instances, not "methods" or "anonymous-methods."

Using a custom Functional Interface

"Lambda" expressions only work with Functional Interfaces.

A functional interface defines the target type of a lambda expression.

The "var" keyword introduced in "Java 10" cannot be used to infer a lambda expression. ("Cannot infer type": lambda expressions require an explicit target type.)

The "java.util.function" package

The "java.util.function" package comes with a set of pre-defined functional interfaces.

1) Predicate

Predicate is a functional interface that has the functional method "boolean test(T t)". It accepts "one argument" and returns a boolean (true if the input argument matches the predicate, otherwise false).

1.1) Predicate as a method parameter

Predicates can be passed as method parameters:

1.2) Composed predicate (AND and OR)

The "default Predicate and(Predicate other)" method in the "Predicate" interface is a "non-abstract" method. It returns the logical AND of this predicate and the other predicate.

The "default Predicate or(Predicate other)" method in the "Predicate" interfaceis a "non-abstract" method. It returns the logical OR of this predicate and the other predicate.

1.3) Predicate negation

The "default Predicate negate()" method in the "Predicate" interface is a "non-abstract" method. It returns a predicate that represents the logical negation of this predicate.

2) BiPredicate

BiPredicate is a functional interface that has the functional method "boolean test(T t, U u)". It accepts "two arguments" and returns a boolean (true if the input arguments match the predicate, otherwise false).

The "BiPredicate" interface also contains three "default" "non-abstract" methods: and(), or(), and negate().

3) Supplier

Supplier is a functional interface that has the functional method "T get()". It accepts "zero arguments" and returns a result of type T.

4) Consumer

Consumer is a functional interface that has the functional method "void accept(T t)". It accepts a single argument and returns no result.

The "default Consumer andThen(Consumer after)" method in the "Consumer" interface is a "non-abstract" method. It returns a composed Consumer that performs in sequence this operation followed by the after operation.

My Name is: Leonardo DiCaprio
My Name is: LEONARDO DICAPRIO

5) BiConsumer

BiConsumer is a functional interface that has the functional method "void accept(T t, U u)". It accepts two arguments and returns no result.

The "default BiConsumer andThen(BiConsumer after)" is a "default" "non-abstract" method in the "BiConsumer" interface. It returns a composed BiConsumer that performs in sequence this operation followed by the after operation.

My Name is 'Leonardo DiCaprio', I am '32'.
My Name is 'LEONARDO DICAPRIO', I am '32'.

6) Function

Function is a functional interface that has the functional method "R apply(T t)". It accepts one argument and returns one result.

The "default Function compose(Function before)" is a "default" "non-abstract" method in the "Function" interface.

It returns a composed function that first applies the before function to its input, and then applies this function to the result.

The "default Function andThen(Function after)" is a "default" "non-abstract" method in the "Function" interface.

It returns a composed function that first applies this function to its input, and then applies the after function to the result.

7) BiFunction

BiFunction is a functional interface that has the functional method "R apply(T t, U u)". It accepts two arguments and produces a result.

The "default BiFunction andThen(Function after)" is a "default" "non-abstract" method in the "BiFunction" interface.

It returns a composed function that first applies this function to its input, and then applies the after function to the result.

8) UnaryOperator

UnaryOperator is a functional interface that extends another functional interface Function. Its functional method is R apply(T t), the one extended from Function.

UnaryOperator 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.

The "static UnaryOperator identity()" is a "static" "non-abstract" method in the "UnaryOperator" interface. It returns a unary operator that always returns its input argument.

9) BinaryOperator

BinaryOperator is a functional interface that extends another functional interface BiFunction. Its functional method is R apply(T t, U u), the one extended from BiFunction.

It represents an operation upon two operands of the same type, producing a result of the same type as the operands.

This is a specialization of BiFunction for the case where the operands and the result are all of the same type.

The "static BinaryOperator minBy(Comparator comparator)" is a "static" "non-abstract" method in the "BinaryOperator" interface. It returns a BinaryOperator which returns the lesser of two elements according to the specified Comparator.

The "static BinaryOperator maxBy(Comparator comparator)" is a "static" "non-abstract" method in the "BinaryOperator" interface. It returns a BinaryOperator which returns the greater of two elements according to the specified Comparator.

Lambda Benefits

1) A lambda helps in creating a function without belonging to any class.

2) It allows you to treat a piece of functionality as a method argument or code as data.

3) A lambda expression can be passed around as if it were an object and executed on demand.

Index
Modern Java - What’s new in Java 9 to Java 17

32 min

What is differences between JDK, JVM and JRE ?

2 min

What is ClassLoader in Java ?

2 min

Object Oriented Programming (OOPs) Concept

17 min

Concurrency in Java: Creating and Starting a Thread

12 min

Concurrency in Java: Interrupting and Joining Threads

5 min

Concurrency in Java: Race condition, critical section, and atomic operations

13 min

Concurrency in Java: Reentrant, Read/Write and Stamped Locks

11 min

Concurrency in Java: "synchronized" and "volatile" keywords

10 min

Concurrency in Java: using wait(), notify() and notifyAll()

6 min

Concurrency in Java: What is "Semaphore" and its use?

2 min

Concurrency in Java: CompletableFuture and its use

18 min

Concurrency in Java: Producer-consumer problem using BlockingQueue

2 min

Concurrency in Java: Producer-Consumer Problem

2 min

Concurrency in Java: Thread pools, ExecutorService & Future

14 min

Java 8 Lambdas, Functional Interface & "static" and "default" methods

28 min

Method Reference in Java (Instance, Static, and Constructor Reference)

9 min

What’s new in Java 21: A Tour of its Most Exciting Features

14 min

Java Memory Leaks & Heap Dumps (Capturing & Analysis)

9 min

Memory footprint of the JVM (Heap & Non-Heap Memory)

15 min