Lambda expressions

 Lambda expression is Anonymous function.

Anonymous function means:

1) does not have name - nameless

2) does not have return type

3) does not have access modifier


-> Functional interfaces must have only and only abstract method. 

-> Lambda expressions can be invoked only through functional interfaces.


-> simple functional interface

package org.example.lambdaExpressions;

@FunctionalInterface
public interface Cab {
void bookCab();
}
package org.example.lambdaExpressions;

public class Ola implements Cab{
@Override
public void bookCab() {
System.out.println("Ola cab is booked");
}
}
package org.example.lambdaExpressions;

public class Main {
public static void main(String[] args) {
Ola ola = new Ola();
ola.bookCab();

Cab cab = new Ola();
cab.bookCab();
}
}


There is no need to initialize class and implement this functional interface. Simplest way to do it is:

package org.example.lambdaExpressions;

public class Main {
public static void main(String[] args) {
Cab cab = () -> System.out.println("Ola cab is booked");
cab.bookCab();
}
}


-> functional interface with parameter list

package org.example.lambdaExpressions;

@FunctionalInterface
public interface Cab {
void bookCab(String source, String destination);
}
package org.example.lambdaExpressions;

public class Ola implements Cab{
@Override
public void bookCab(String source, String destination) {
System.out.println("Ola cab is booked from " + source + " to " + destination);
}
}
package org.example.lambdaExpressions;

public class Main {
public static void main(String[] args) {
Cab cab = new Ola();
cab.bookCab("Baku", "Absheron");
}
}


Now let's directly write lambda expression:

package org.example.lambdaExpressions;

public class Main {
public static void main(String[] args) {
Cab cab = (source, destination) -> System.out.println("Ola cab is booked from " + source + " to " + destination);
cab.bookCab("Baku", "Absheron");
}
}


-> functional interface with parameter list and return type:

package org.example.lambdaExpressions;

@FunctionalInterface
public interface Cab {
String bookCab(String source, String destination);
}
package org.example.lambdaExpressions;

public class Ola implements Cab {
@Override
public String bookCab(String source, String destination) {
System.out.println("Ola cab is booked from " + source + " to " + destination);
return "Price is 5 manat";
}
}
package org.example.lambdaExpressions;

public class Main {
public static void main(String[] args) {
Cab cab = new Ola();
System.out.println(cab.bookCab("Baku", "Abheron"));

Cab cab1 = (source, destination) -> {
System.out.println("Ola cab is booked from " + source + " to " + destination);
return "Price is 5 manat";
};
System.out.println(cab1.bookCab("Baku", "Absheron"));
}
}



->

package org.example.lambdas;

public class RunnableLambdaExample {
public static void main(String[] args) {
// Prior to Java 8
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Inside Runnable 1");
}
};
new Thread(runnable).start();

// Java 8
Runnable runnableLambda = () -> {
System.out.println("Inside Runnable 2");
};
new Thread(runnableLambda).start();

Runnable runnableLambda1 = () -> System.out.println("Inside Runnable 3");
new Thread(runnableLambda1).start();

new Thread(() -> System.out.println("Inside Runnable 4")).start();
}
}



->

package org.example.lambdas;

import java.util.Comparator;

public class ComparatorLambdaExample {
public static void main(String[] args) {
// prior java 8
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};

System.out.println("Result of the comparator is : " + comparator.compare(3, 2));

// java 8
Comparator<Integer> comparatorLambda = (Integer a, Integer b) -> a.compareTo(b);
System.out.println("Result of the comparator using lambda is : " + comparatorLambda.compare(3, 2));
}
}

-----------------------------------------------------------------------------------------------------------------------------

Predefined Functional Interfaces: 1-Predicate 2-Function 3-Consumer 4-Supplier

1. Predicate. Has abstract method test()

Predicate only takes one parameter and returns boolean value. Use only if you have conditional checks in your program

->

package org.example.lambdaExpressions.predicates;

import java.util.function.Predicate;

public class Demo1 {
public static void main(String[] args) {
// ex1
Predicate<Integer> p = (i) -> i > 10;
System.out.println(p.test(20));

// ex2: check the length of given string is greater than 4 or not
Predicate<String> p1 = (s) -> s.length() > 4;
System.out.println(p1.test("a"));

// ex3: Print array elements whose size is > 4
String[] names = {"David", "Scott", "Smith", "John", "Mary"};
for(String s : names) {
if(p1.test(s))
System.out.println(s);
}
}
}


->

package org.lesson19;

public class Employee {
public String name;
public Integer salary;
public Integer experience;

public Employee() {
}

public Employee(String name, Integer salary, Integer experience) {
this.name = name;
this.salary = salary;
this.experience = experience;
}

@Override
public String toString() {
return "Employee{name='%s', salary=%d, experience=%d}"
.formatted(name, salary, experience);
}
}
package org.example.lambdaExpressions.predicates;

import java.util.function.Predicate;

public class Demo2 {
public static void main(String[] args) {
// ex1: emp obj -> return name if salary > 50K && exp > 3
Predicate<Employee> p1 = (e) -> (e.salary > 50000 && e.experience > 3);
Employee e1 = new Employee("John", 60000, 5);
Employee e2 = new Employee("Mike", 40000, 4);
System.out.println(p1.test(e1));
System.out.println(p1.test(e2));
}
}



-> Predicate and

package org.example.lambdaExpressions.predicates;

import java.util.function.Predicate;

public class Demo3 {
public static void main(String[] args) {
// ex1: and
int[] arr = {5, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65};
Predicate<Integer> p1 = i -> i % 2 == 0;
Predicate<Integer> p2 = i -> i > 50;
for (int i : arr) {
if (p1.and(p2).test(i))
System.out.println(i);
}
}
}


-> Predicate or

package org.example.lambdaExpressions.predicates;

import java.util.function.Predicate;

public class Demo3 {
public static void main(String[] args) {
// ex1: and
int[] arr = {5, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65};
Predicate<Integer> p1 = i -> i % 2 == 0;
Predicate<Integer> p2 = i -> i > 50;
for (int i : arr) {
if (p1.or(p2).test(i))
System.out.println(i);
}
}
}



2. Function. Has abstract method apply()

As a parameter list it takes T type and returns R as return type.

package org.example.lambdaExpressions.function;

import java.util.function.Function;

public class Main {
public static void main(String[] args) {
Function<Integer, Integer> f = n -> n * n;
System.out.println(f.apply(5));

Function<String, Integer> f1 = s -> s.length();
System.out.println(f1.apply("Parvin"));
}
}


->

package org.example.lambdaExpressions.function;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class Main {
public static void main(String[] args) {
List<Employee> list = new ArrayList<>();
list.add(new Employee("David", 50000));
list.add(new Employee("John", 30000));
list.add(new Employee("Mary", 20000));
Function<Employee, Integer> f = e -> {
int salary = e.salary;
if (salary >= 10000 && salary <= 20000)
return (salary * 10 / 100);
else if (salary > 20000 & salary <= 30000)
return (salary * 20 / 100);
else if (salary > 30000 && salary <= 50000)
return (salary * 30 / 100);
else return (salary * 40 / 100);
};
for (Employee e : list) {
int bonus = f.apply(e);
System.out.println("Name: " + e.name + " salary: " + e.salary + " and bonus: " + bonus);
}
}
}


->Now lets apply Function with Predicate

package org.example.lambdaExpressions.function;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

public class Main {
public static void main(String[] args) {
List<Employee> list = new ArrayList<>();
list.add(new Employee("David", 50000));
list.add(new Employee("John", 30000));
list.add(new Employee("Mary", 20000));
Function<Employee, Integer> f = e -> {
int salary = e.salary;
if (salary >= 10000 && salary <= 20000)
return (salary * 10 / 100);
else if (salary > 20000 & salary <= 30000)
return (salary * 20 / 100);
else if (salary > 30000 && salary <= 50000)
return (salary * 30 / 100);
else return (salary * 40 / 100);
};

Predicate<Integer> p = b -> b > 5000;

for (Employee e : list) {
int bonus = f.apply(e); // Function
if (p.test(bonus)) // Predicate
System.out.println("Name: " + e.name + " salary: " + e.salary + " and bonus: " + bonus);
}
}
}


-> Function chaining: andThen(), compose()

package org.example.lambdaExpressions.function;

import java.util.function.Function;

public class Demo3 {
public static void main(String[] args) {
Function<Integer, Integer> f1 = n -> n * 2;
Function<Integer, Integer> f2 = n -> n * n * n;
System.out.println(f1.andThen(f2).apply(2));
System.out.println(f1.compose(f2).apply(2));
}
}


3. Consumer. Has abstract method accept()

package org.example.lambdaExpressions.consumer;

import java.util.function.Consumer;

public class Demo1 {
public static void main(String[] args) {
Consumer<String> c = s -> System.out.println(s);
c.accept("Hello");
}
}


->

package org.example.lambdaExpressions.consumer;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class Demo2 {
public static void main(String[] args) {
List<Employee> list = new ArrayList<>();
list.add(new Employee("David", 50000, "male"));
list.add(new Employee("John", 30000, "male"));
list.add(new Employee("Mary", 20000, "female"));
list.add(new Employee("Scott", 60000, "male"));

// Function
Function<Employee, Integer> f = employee -> (employee.salary * 10) / 100; // task1

// Predicate
Predicate<Integer> p = b -> b > 5000; // task2

// Consumer
Consumer<Employee> c = emp -> {
System.out.println(emp.name);
System.out.println(emp.salary);
System.out.println(emp.gender);
};

for (Employee e : list) {
int bonus = f.apply(e);
if (p.test(bonus)) {
c.accept(e);
System.out.println(bonus);
}
}
}
}


package org.lesson20;

public class Employee {
public String name;
public Integer salary;
public String gender;
public Integer experience;

public Employee() {
}

public Employee(String name, Integer salary, String gender) {
this.name = name;
this.salary = salary;
this.gender = gender;
}

public Employee(String name, Integer salary) {
this.name = name;
this.salary = salary;
}

public Employee(String name, Integer salary, Integer experience) {
this.name = name;
this.salary = salary;
this.experience = experience;
}

public Employee(String name, Integer salary, String gender, Integer experience) {
this.name = name;
this.salary = salary;
this.gender = gender;
this.experience = experience;
}

@Override
public String toString() {
return "Employee{name='%s', salary=%d, experience=%d}"
.formatted(name, salary, experience);
}
}


-> Consumer chaining


package org.example.lambdaExpressions.consumer;

import java.util.function.Consumer;

public class Demo3 {
public static void main(String[] args) {
Consumer<String> c1 = s -> System.out.println(s + " " + "is White");
Consumer<String> c2 = s -> System.out.println(s + " " + "is having four legs");
Consumer<String> c3 = s -> System.out.println(s + " " + "is eating grass");

c1.andThen(c2).andThen(c3).accept("Cow");

Consumer<String> c4 = c1.andThen(c2).andThen(c3);
c4.accept("Cow");
}
}


4.Supplier. Has abstreact method get()

package org.example.lambdaExpressions.supplier;

import java.util.Date;
import java.util.function.Supplier;

public class Demo1 {
public static void main(String[] args) {
Supplier<Date> s = () -> new Date();
System.out.println(s.get());
}
}


-----------------------------------------------------------------------------------------------------------------------------

1. Consumer

package org.example.lambdas.consumer;

import java.util.List;

public class Student {
private String name;
private int gradeLevel;
private double gpa;
private String gender;
private List<String> activities;

public Student(String name, int gradeLevel, double gpa, String gender, List<String> activities) {
this.name = name;
this.gradeLevel = gradeLevel;
this.gpa = gpa;
this.gender = gender;
this.activities = activities;
}

public List<String> getActivities() {
return activities;
}

public void setActivities(List<String> activities) {
this.activities = activities;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getGradeLevel() {
return gradeLevel;
}

public void setGradeLevel(int gradeLevel) {
this.gradeLevel = gradeLevel;
}

public double getGpa() {
return gpa;
}

public void setGpa(double gpa) {
this.gpa = gpa;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", gradeLevel=" + gradeLevel +
", gpa=" + gpa +
", gender='" + gender + '\'' +
", activities=" + activities +
'}';
}
}
package org.example.lambdas.consumer;

import java.util.Arrays;
import java.util.List;

public class StudentDatabase {
public static List<Student> getAllStudents() {
// 2nd grade students
Student student1 = new Student("Adam", 2, 3.6, "male", Arrays.asList("swimming", "basketball", "volleyball"));
Student student2 = new Student("Jenny", 2, 3.8, "female", Arrays.asList("swimming", "gymnastics", "soccer"));

// 3rd grade students
Student student3 = new Student("Emily", 3, 4, "female", Arrays.asList("swimming", "gymnastics", "aerobics"));
Student student4 = new Student("Dave", 3, 3.9, "male", Arrays.asList("swimming", "gymnastics", "soccer"));

// 4th grade students
Student student5 = new Student("Sophia", 4, 3.5, "female", Arrays.asList("swimming", "dancing", "football"));
Student student6 = new Student("James", 4, 3.9, "male", Arrays.asList("swimming", "basketball", "baseball", "football"));

List<Student> students = Arrays.asList(student1, student2, student3, student4, student5, student6);
return students;
}
}
package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.List;
import java.util.function.Consumer;

public class Main {

public static Consumer<Student> c1 = s -> System.out.println(s);
public static Consumer<Student> c2 = s -> System.out.println(s.getName());
public static Consumer<Student> c3 = s -> System.out.println(s.getActivities());

public static void main(String[] args) {
printStudents();
// printNameAndActivities();
// printNameAndActivitiesUsingCondition();
}

public static void printStudents() {
List<Student> list = StudentDatabase.getAllStudents();
// list.forEach(c1);
list.forEach(student -> c1.accept(student));
}

public static void printNameAndActivities() {
List<Student> list = StudentDatabase.getAllStudents();
list.forEach(c2.andThen(c3));
}

public static void printNameAndActivitiesUsingCondition() {
List<Student> list = StudentDatabase.getAllStudents();
list.forEach(student -> {
if(student.getGradeLevel() >= 3) {
c2.andThen(c3).accept(student);
}
});
}
}


2. BiConsumer

package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.List;
import java.util.function.BiConsumer;

public class BiConsumerExample {
public static void main(String[] args) {
BiConsumer<String, String> biConsumer = (a, b) -> System.out.println("a :" + a + " b:" + b);
biConsumer.accept("java7", "java8");

BiConsumer<Integer, Integer> multiply = (a, b) -> System.out.println("Multiplication is: " + (a * b));
multiply.accept(2, 3);

BiConsumer<Integer, Integer> divide = (a, b) -> System.out.println("Division is: " + (a / b));
multiply.andThen(divide).accept(10, 2);

nameAndActivities();
}

public static void nameAndActivities() {
BiConsumer<String, List<String>> biConsumer = (name, activities) -> System.out.println(name + " : " + activities);
List<Student> list = StudentDatabase.getAllStudents();
list.forEach(student -> biConsumer.accept(student.getName(), student.getActivities()));
}
}


3. Predicate

package org.example.lambdas;

import java.util.function.Predicate;

public class PredicateExample {

public static Predicate<Integer> p1 = i -> i % 2 == 0;
public static Predicate<Integer> p2 = i -> i % 5 == 0;

public static void main(String[] args) {
System.out.println(p1.test(3));
predicateAnd();
predicateOr();
predicateNegate();
}

public static void predicateAnd() {
System.out.println("Predicate and result is: " + p1.and(p2).test(10));
System.out.println("Predicate and result is: " + p1.and(p2).test(9));
}

public static void predicateOr() {
System.out.println("Predicate or result is: " + p1.or(p2).test(10));
System.out.println("Predicate or result is: " + p1.or(p2).test(8));
}

public static void predicateNegate() {
System.out.println("Predicate or result with negate is: " + p1.or(p2).negate().test(10));
}
}


package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.List;
import java.util.function.Predicate;

public class PredicateStudentExample {

public static Predicate<Student> p1 = s -> s.getGradeLevel() >= 3;
public static Predicate<Student> p2 = s -> s.getGpa() >= 3.9;

public static void main(String[] args) {
filterStudentByGradeLevel();
filterStudentByGpa();
filterStudents();
}

public static void filterStudentByGradeLevel() {
List<Student> list = StudentDatabase.getAllStudents();
list.forEach(student -> {
if (p1.test(student))
System.out.println(student);
});
// StudentDatabase.getAllStudents().stream().filter(s -> s.getGradeLevel() > 3).forEach(System.out::println);
}

public static void filterStudentByGpa() {
List<Student> list = StudentDatabase.getAllStudents();
list.forEach(student -> {
if (p2.test(student))
System.out.println(student);
});
}

public static void filterStudents() {
List<Student> list = StudentDatabase.getAllStudents();
list.forEach(student -> {
if (p1.and(p2).test(student))
System.out.println(student);
});
}
}


Combining Predicate and Consumer

package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class PredicateAndConsumerExample {

public static Predicate<Student> p1 = s -> s.getGradeLevel() >= 3;
public static Predicate<Student> p2 = s -> s.getGpa() >= 3.9;
public static BiConsumer<String, List<String>> biConsumer = (name, activities) -> System.out.println(name + " : " + activities);
public static Consumer<Student> c1 = student -> {
if (p1.and(p2).test(student))
biConsumer.accept(student.getName(), student.getActivities());
};

public static void main(String[] args) {
List<Student> list = StudentDatabase.getAllStudents();
printNameAndActivities(list);
}

public static void printNameAndActivities(List<Student> students) {
students.forEach(c1);
}
}


4. BiPredicate

package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class PredicateAndConsumerExample {

public static Predicate<Student> p1 = s -> s.getGradeLevel() >= 3;
public static Predicate<Student> p2 = s -> s.getGpa() >= 3.9;
public static BiPredicate<Integer, Double> biPredicate = (gradeLevel, gpa) -> gradeLevel >= 3 && gpa >= 3.9;
public static BiConsumer<String, List<String>> biConsumer = (name, activities) -> System.out.println(name + " : " + activities);
public static Consumer<Student> c1 = student -> {
if (biPredicate.test(student.getGradeLevel(), student.getGpa()))
biConsumer.accept(student.getName(), student.getActivities());
};

public static void main(String[] args) {
List<Student> list = StudentDatabase.getAllStudents();
printNameAndActivities(list);
}

public static void printNameAndActivities(List<Student> students) {
students.forEach(c1);
}
}


5. Function

package org.example.lambdas;

import java.util.function.Function;

public class FunctionExample {

public static Function<String, String> function = name -> name.toUpperCase();
public static Function<String, String> addSomeString = name -> name.toUpperCase().concat("default");

public static void main(String[] args) {
System.out.println("Result is : " + function.apply("java8"));
System.out.println("Result is : " + addSomeString.apply("java8"));
System.out.println("Result of compose is : " + function.compose(addSomeString).apply("java8"));
}
}


package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FunctionStudentExample {

public static Function<List<Student>, Map<String, Double>> function = (students -> {
Map<String, Double> map = new HashMap<>();
students.forEach(student -> {
map.put(student.getName(), student.getGpa());
});
return map;
});

public static void main(String[] args) {
System.out.println(function.apply(StudentDatabase.getAllStudents()));

// System.out.println(StudentDatabase.getAllStudents().stream()
// .collect(Collectors.toMap(Student::getName, Student::getGpa)));
}
}


6. BiFunction

package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Predicate;

public class BiFunctionExample {

public static BiFunction<List<Student>, Predicate<Student>, Map<String, Double>> biFunction = (students, predicate) -> {
Map<String, Double> map = new HashMap<>();
students.forEach(student -> {
if (predicate.test(student))
map.put(student.getName(), student.getGpa());
});
return map;
};

public static void main(String[] args) {
System.out.println(biFunction.apply(StudentDatabase.getAllStudents(), s -> s.getGpa() >= 3.9));
}
}


7. UnaryOperator and BinaryOperator Functional interface

package org.example.lambdas;

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {

public static UnaryOperator<String> unaryOperator = s -> s.concat("default");

public static void main(String[] args) {
System.out.println(unaryOperator.apply("java8"));
}
}
package org.example.lambdas;

import java.util.Comparator;
import java.util.function.BinaryOperator;

public class BinaryOperatorExample {

public static Comparator<Integer> comparator = (a, b) -> a.compareTo(b);

public static void main(String[] args) {
BinaryOperator<Integer> binaryOperator = (a, b) -> a * b;
System.out.println(binaryOperator.apply(3, 4));

BinaryOperator<Integer> maxBy = BinaryOperator.maxBy(comparator);
System.out.println("Result of maxBy is : " + maxBy.apply(4, 5));

BinaryOperator<Integer> minBy = BinaryOperator.maxBy(comparator);
System.out.println("Result of minBy is : " + minBy.apply(4, 5));
}
}


8. Supplier

package org.example.lambdas;

import org.example.lambdas.consumer.Student;
import org.example.lambdas.consumer.StudentDatabase;

import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

public class SupplierExample {
public static void main(String[] args) {
Supplier<Student> studentSupplier = () -> {
return new Student("Parvin", 1, 3.6, "male", Arrays.asList("swimming", "football", "volleyball"));
};

Supplier<List<Student>> listSupplier = () -> StudentDatabase.getAllStudents();

System.out.println("Student is : " + studentSupplier.get());
System.out.println("Students are : " + listSupplier.get());
}
}


Method reference

package org.example.lambdas.methodReference;

import java.util.function.Function;

public class FunctionMethodReferenceExample {

public static Function<String, String> toUpperCaseLambda = s -> s.toUpperCase();
public static Function<String, String> toUpperCaseMethodReference = String::toUpperCase;

public static void main(String[] args) {
System.out.println(toUpperCaseLambda.apply("java8"));
System.out.println(toUpperCaseMethodReference.apply("java8"));
}
}



















Комментарии

Популярные сообщения из этого блога

Lesson1: JDK, JVM, JRE

SE_21_Lesson_11: Inheritance, Polymorphism

SE_21_Lesson_9: Initialization Blocks, Wrapper types, String class