Wednesday, 5 June 2019

Java 8 | Java Comparator with Lambda

Comparator is used when we want to sort a collection of objects which can be compared with each other. This comparison can be done using Comparable interface as well, but it restrict us compare the objects in a natural order. If we want to sort this collection, based on multiple criterias/fields, then Comparator can be used for this purpose.

Quick Reference – To create instance of Comparator

// Sort all student by first name
Comparator comparator = Comparator.comparing(std -> std.getFirstName());

// OR you can use below
Comparator comparator = Comparator.comparing(Student::getFirstName);

// OR you can use below
Comparator comparator = (std1, std2)-> std1.getFirstName().compareTo(std2.getFirstName());

// To sort in reverse order.
Comparator reversedComparator = comparator.reversed();

// Sorting on multiple fields; Group by.
Comparator groupByComparator= Comparator.comparing(Student::getFirstName)
                     .thenComparing(Student::getLastName);

Take Sample Student class

We will use Student with four attributes id, firstName, lastName and age.

import java.util.ArrayList;
import java.util.List;

class Student {
     private Integer id;
     private String firstName;
     private String lastName;
     private Integer age;

     public Student(Integer id, String firstName, String lastName, Integer age) {
           this.id = id;
           this.firstName = firstName;
           this.lastName = lastName;
           this.age = age;
     }

     public String getFirstName() {
           return firstName;
     }

     public String getLastName() {
           return lastName;
     }

     @Override
     public String toString() {
           return String.format("(%d|%s|%s|%d)", id, firstName, lastName, age);
     }

     /**
      * Return list of student.
      * @return list
      */
     public static List getStudentsList() {
          
           List students = new ArrayList<>();
           students.add(new Student(6, "Sameer", "Kumar", 50));
           students.add(new Student(2, "Ritesh", "Kumar", 28));
           students.add(new Student(3, "Anurag", "Singh", 30));
           students.add(new Student(5, "Rajesh", "Kumar", 28));
           students.add(new Student(4, "Ravi", "Goswami", 30));
          
           return students;
     }
}


Sort by first name

Basic use case, where list of students will be sorted based on their first name.

public class ComparatorExample {

     /**
      * This method to sort the students list by First name.
      * @param students
      */
     private static void sortByFirstName(List students) {
           System.out.println("Student list before sorting: ");
           System.out.println(students);

           // Sort all student by first name
           students.sort(Comparator.comparing(std -> std.getFirstName()));

           // OR you can use below
           students.sort(Comparator.comparing(Student::getFirstName));

           // OR you can use below
           students.sort((std1, std2) -> std1.getFirstName().compareTo(std2.getFirstName()));

           // Collections.sort(students, (std1, std2) -> std1.getFirstName().compareTo(std2.getFirstName()));

           System.out.println("Sorted Student list by first name: ");
           System.out.println(students);
     }

     /**
      * Driver method.
      * @param args
      */
     public static void main(String[] args) {
           List students = Student.getStudentsList();
           sortByFirstName(students);
     }
}

Sort by first name – reverse order

What if we want to sort on first name but in revered order? really easy solution is to use reversed() method.

    public class ComparatorExample {

     /**
      * This method to sort the students list by First name in reversed order.
      * @param students
      */
     private static void sortByFirstNameReversed(List students) {
           System.out.println("Student list before sorting: ");
           System.out.println(students);

           // Sort all student by first name and then reversed
           Comparator comparator = Comparator.comparing(std -> std.getFirstName());
           students.sort(comparator.reversed());

           System.out.println("Sorted Student list by first name reversed: ");
           System.out.println(students);
     }

     /**
      * Driver method.
      * @param args
      */
     public static void main(String[] args) {
           List students = Student.getStudentsList();
           sortByFirstNameReversed(students);
     }
}

Sort on multiple fields – thenComparing()

Here we are sorting list of students first by their first name, and then sort again the list of last name. Just as we apply sorting on SQL statements. It’s actually a very good feature.

Now you don’t need to always use sorting on multiple fields in SQL select statements, you can sort them in java as well.

public class ComparatorExample {

     /**
      * This method to sort the student list by multiple columns.
      * @param students
      */
     private static void sortByMultipleFields(List students) {
           System.out.println("Student list before sorting: ");
           System.out.println(students);

           // Sorting on multiple fields; Group by.
           Comparator groupByComparator =
                         Comparator.comparing(Student::getFirstName)
                     .thenComparing(Student::getLastName);

           students.sort(groupByComparator);

           System.out.println("Sorted Student list by first name and last name: ");
           System.out.println(students);
     }

     /**
      * Driver method.
      * @param args
      */
     public static void main(String[] args) {
           List students = Student.getStudentsList();
           sortByMultipleFields(students);
     }
}

Parallel sort (with multiple threads)

You can sort the collection of objects in parallel using multiple threads as well. It is going to be very fast if collection is big enough having thousands of objects. For small collection of objects, normal sorting is good enough and recommended.

public class ComparatorExample {

     private static void parallelSortByLastName(List students) {
           System.out.println("Student list before sorting: ");
           System.out.println(students);

           Student[] stdArray = students.toArray(new Student[students.size()]);

           Comparator comparator = Comparator.comparing(std -> std.getLastName());

           // Parallel sorting
           Arrays.parallelSort(stdArray, comparator);

           System.out.println("Parallel sort to Student list by last name: ");
           System.out.println(Arrays.asList(stdArray));
     }

     /**
      * Driver method.
      * @param args
      */
     public static void main(String[] args) {
           List students = Student.getStudentsList();
           parallelSortByLastName(students);
     }
}

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...