Sunday, September 24, 2017

Lambda (Java 8) - Transfer one type of object to another type of object

We will assume that we have list of Students to convert into list of Persions.

public class Student {
    private String name;
    private String school;
    private int age;

    public Student(String name, String school, int age) {
        this.name = name;
        this.school = school;
        this.age = age;
    }

    // getters/setters should come here

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", school='" + school + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Person {
    private String fullName;
    private int age;

    public Person(String fullName, int age) {
        this.fullName = fullName;
        this.age = age;
    }

    //getters/setters should come here

    @Override
    public String toString() {
        return "Person{" +
                "fullName='" + fullName + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

In this article, I'm going to use functional interface call Funcation to achieve this.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class StudentApplication {
    public static void main(String[] args) {
        Function<Student, Person> functionStuToPer = student -> new Person(student.getName(), student.getAge());

        List<Student> students = Arrays.asList(
                new Student("Tharanga", "UOC", 22),
                new Student("Ruwan", "UOM", 24),
                new Student("Ruvini", "UOK", 20),
                new Student("Randika", "TOUC", 25),
                new Student("Amara", "UOR", 23)
        );

        List<Person> persons = convertStudentListToPerson(students, functionStuToPer);
        persons.forEach(System.out::println);

    }

    private static List<Person> convertStudentListToPerson(List<Student> students, Function<Student, Person> functions) {
        List<Person> persons = new ArrayList<>();
        for (Student student: students) {
            persons.add(functions.apply(student));
        }
        return persons;
    }
}


Enjoy...!!

Lambda (Java 8) - How to sort and filter array

In this article, I'm going to explain about the way we can sort and filter an array using lambda expressions.

TASK 1

We will assume that, we have a list of students as follows:
 List<Student> students = Arrays.asList(
         new Student("Tharanga", "UOC", 22),
         new Student("Ruwan", "UOM", 24),
         new Student("Ruvini", "UOK", 20),
         new Student("Randika", "TOUC", 25),
         new Student("Amara", "UOR", 23)
);

In this scenario, we will assume that we have to sort the students by name:

Initially, how we cater this without lambda expression:
Collections.sort(students, new Comparator<Student>() {
       @Override
       public int compare(Student o1, Student o2) {
           return o1.getName().compareTo(o2.getName());
       }
});

Now will cater this requirement with lambda expressions.
 Collections.sort(students, (o1, o2) -> o1.getName().compareTo(o2.getName()));

Note: Since 'Comparator' interface is a functional interface we can sort the object list as above.

TASK 2

In here, we will assume that we need to filter the students, name starting with 'R'

Without lambda expression we can achieve this as below.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class StudentApplication {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("Tharanga", "UOC", 22),
                new Student("Ruwan", "UOM", 24),
                new Student("Ruvini", "UOK", 20),
                new Student("Randika", "TOUC", 25),
                new Student("Amara", "UOR", 23)
        );

        Collections.sort(students, (o1, o2) -> o1.getName().compareTo(o2.getName()));

        printConditionally(students, new Condition() {
            @Override
            public boolean test(Student student) {
                return student.getName().startsWith("R");
            }
        });

    }

    private static void printConditionally(List<Student> students, Condition condition) {
        for (Student student: students) {
            if(condition.test(student)) {
                System.out.println(student);
            }
        }
    }
}

interface Condition {
    boolean test(Student student);
} 

How we achieve this using lambda expression.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

public class StudentApplication {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("Tharanga", "UOC", 22),
                new Student("Ruwan", "UOM", 24),
                new Student("Ruvini", "UOK", 20),
                new Student("Randika", "TOUC", 25),
                new Student("Amara", "UOR", 23)
        );

        Collections.sort(students, (o1, o2) -> o1.getName().compareTo(o2.getName()));

        printConditionally(students, student -> student.getName().startsWith("R"));

    }

    private static void printConditionally(List<Student> students, Predicate<Student> predicate) {
        for (Student student: students) {
            if(predicate.test(student)) {
                System.out.println(student);
            }
        }
    }
}

Note: Java 8, OFTB support many functional interfaces such as "Predicate". You can find more on here.

Note: Find more information about funcational interfaces here.

Lambda (Java 8) - Functional Interface

To write a lambda expression, the interface should have only one abstract method. If an interface has more than one abstract method, we cannot write lambda expression.

When we work as a team, someone creates an interface to write a lambda expression. Later, another team member can add another abstract method to that interface to fulfill his requirement. But in this scenario, that change will effect to the lambda expression and it will not work.

To avoid above scenarios, we need to tell specifically, this interface should have only one abstract method.

We have a lovely annotation to cater this requirement as @FunctionalInterface. It restricts the adding more than one abstract method to the interface.

Find the below sample:
@FunctionalInterface
public interface Greeting {
    String perform(String s) ;
}


Enjoy...!!

Lambda (Java 8) - How to use Runnable interface

In this article, I'm going to explain the way we can use lambda to implement the Runnable interface.

General scenario is below:
  
   ...
   Thread myThread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Printed inside runnable");
            System.out.println(Thread.currentThread().getId());
        }
   });
   myThread.start();
   ...
Below is the code segment, same above implementation with lambda.
   ...
        Thread myLambdaThread = new Thread(() -> {
            System.out.println("printed inside the lambda expression");
            System.out.println("Thread Id: " + Thread.currentThread().getId());
        });

        myLambdaThread.start();
   ...


  • Empty parentheses: because run() method doesn't allow any arguments.
  • If there is more than one line of the implementation, we need to write the implementation inside the curly brackets.


Note: Runable interface only one method call run(), so we can write lambda expression. If there is more than one method declaration inside a interface, we cannot write lambda expression.

Enjoy..!!

Saturday, September 23, 2017

Lambda (Java 8) - Interface Implementation

In this post, I'm going to describe the way, we use lamdba to 'Interface Implementation'.

Find the below steps:

1. Create an interface as below
public interface Greeting {
    void perform() ;
}

2. In lambda, you can implement the perform method as below
Greeting greeting = () -> System.out.println("Hello Greeting");

3. Then finally, you can invoke the perform method as below.
...
Greeting greeting = () -> System.out.println("Hello , Greeting");
greeting.perform();
...
In the above scenario, I used empty parentheses, it is because, it should be similar to the method signature.
For an example, If I declare the perform() as perform(String message), lambda expression should be as below.
Greeting greeting = (message) -> System.out.println("Hello " + message);

Note: Here we don't need to specify the parameter type, java automatically sets the relevant type.

When we have a return type, above sample should change like follows.

public interface Greeting {
    String perform(String message) ;
}
Lambda:
Greeting greeting = (message) -> "Hello " + message;
Then, when we execute the perform method, it returns a string value.

Note: If you have to pass a single parameter, you can remove the parentheses as below
Greeting greeting = message -> "Hello " + message;

Enjoy...!!