Functional programming in Java - Concepts
Table of contents
First article: https://zomor.hashnode.dev/functional-programming-in-java
As we have elaborated earlier, the functional paradigm has been introduced to Java since Java 8. In this article, we will discuss further how Java is making it easier to implement the FP
Lambda
Java always had the concept of the interface, a specific case of the class, where we don't implement any methods, we keep them abstract to be implemented in the child class, also the class can inherit multiple interfaces (Unlike classes where you can only extend one)
In Java 8, the annotation (FunctionalInterface) is introduced, this resembles an interface with only one method
Earlier, to implement such interfaces, we needed to create a class that extends that interface and implement this method, or we could have added an anonymous class inside our code, until Lambda
@FunctionalInterface
public interface Animal {
void makeSound();
}
// First method -> Create class that implements the interface
public class Cat implements Animal {
@override
void makeSound() {
System.out.println("MEOW");
}
}
// Second method -> Create anonymous class
Animal dog = new Animal (){
@override
void makeSound() {
System.out.println("BARK");
}
};
// Third method -> Lambda
Animal lion = () -> System.out.println("ROAR");
Simply, Lambdas are a way of writing an anonymous class, and the standard for it is as follows:
// (args) -> {
// Method body ;
// }
// AS A SIMPLIFICATION
// (args) -> return statement; (WITHOUT RETURN KEYWORD)
Method Reference
To make the code even less and readable with lambdas, the method reference is also introduced in Java 8, which is used as follows:
//1. Access the static method
// Lambda
s -> System.out.println(s);
// Method Reference
System.out::println;
// 2. Create new instance
// Lambda
() -> new Person();
// Method Referrence
Person::new;
// 3. Access a method in an instance
// Lambda
() -> person.getName();
// Method Reference
person::getName;
Recursion
Recursion as we understand from its name is a way to implement a specific method with different inputs until a specific condition is met, then we get out of this recursion
int myArr [] = {45, 55, 95, 105};
// Looping method
for (int i = 0; i < myArr.length; i++) {
System.out.println(myArr[i]);
}
// Recursion
void printArray(int[] arr, currentIndex i) {
if (currentIndex == arr.length) return; // Stop condition
System.out.println(arr[i]); // Method implementation
printArray(arr, i + 1); // Recursion
}
printArray(myArr, 0);
Closures in Java
Closure means that if a function contains another function. Inside the inner function, you can still access a variable from the scope of the outer function
Function<Integer, UnaryOperator<Integer>> myFunction = x -> y -> x * y ;
// Inside the inner function (y -> x * y) you are still able to access (x) variable which is defined in the outer scope
Conclusion
In this second article, we have covered a few topics that you need to be aware of while dealing with FP in Java.
In the upcoming article, we will talk more about how to implement functions in Java
You can find more code examples on this repo