Java8 - sorting with Comparator.comparing

Keywords: Mobile Lambda Java

Java8 - using Comparator.comparing for comparison sorting

Sorting with external Comparator comparator

When we need to sort the elements of the collection, we can use java.util.Comparator to create a comparator for sorting. The comparator interface is also a functional interface. We can use lambda expressions. Here is an example,

package com.common;

import java.util.*;
import java.util.stream.Collectors;

public class ComparatorTest {
    public static void main(String[] args) {

        Employee e1 = new Employee("John", 25, 3000, 9922001);
        Employee e2 = new Employee("Ace", 22, 2000, 5924001);
        Employee e3 = new Employee("Keith", 35, 4000, 3924401);

        List<Employee> employees = new ArrayList<>();
        employees.add(e1);
        employees.add(e2);
        employees.add(e3);

        /**
         *     @SuppressWarnings({"unchecked", "rawtypes"})
         *     default void sort(Comparator<? super E> c) {
         *         Object[] a = this.toArray();
         *         Arrays.sort(a, (Comparator) c);
         *         ListIterator<E> i = this.listIterator();
         *         for (Object e : a) {
         *             i.next();
         *             i.set((E) e);
         *         }
         *     }
         *
         *     sort Object to receive a Comparator function interface, you can pass in a lambda expression
         */
        employees.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));

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

        employees.forEach(System.out::println);
    }
}


/**
 * [Employee(name=John, age=25, salary=3000.0, mobile=9922001),
 * Employee(name=Ace, age=22, salary=2000.0, mobile=5924001),
 * Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]
 */
class Employee {
    String name;
    int age;
    double salary;
    long mobile;

    // constructors, getters & setters


    public Employee(String name, int age, double salary, long mobile) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.mobile = mobile;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public long getMobile() {
        return mobile;
    }

    public void setMobile(long mobile) {
        this.mobile = mobile;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Employee{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", salary=").append(salary);
        sb.append(", mobile=").append(mobile);
        sb.append('}');
        return sb.toString();
    }
}

 

Use Comparator.comparing to sort

comparing method 1

Check the internal implementation of the Comparator class. There is also a comparing method, which is implemented as follows,

    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

Its return value is (C1, C2) - > keyextractor. Apply (C1). CompareTo (keyextractor. Apply (C2)); a lambda expression, that is, a comparer. So the example above can also be modified as follows,

package com.common;

import java.util.*;

public class ComparatorTest {
    public static void main(String[] args) {

        Employee e1 = new Employee("John", 25, 3000, 9922001);
        Employee e2 = new Employee("Ace", 22, 2000, 5924001);
        Employee e3 = new Employee("Keith", 35, 4000, 3924401);

        List<Employee> employees = new ArrayList<>();
        employees.add(e1);
        employees.add(e2);
        employees.add(e3);

        /**
         *     @SuppressWarnings({"unchecked", "rawtypes"})
         *     default void sort(Comparator<? super E> c) {
         *         Object[] a = this.toArray();
         *         Arrays.sort(a, (Comparator) c);
         *         ListIterator<E> i = this.listIterator();
         *         for (Object e : a) {
         *             i.next();
         *             i.set((E) e);
         *         }
         *     }
         *
         *     sort Object to receive a Comparator function interface, you can pass in a lambda expression
         */
        employees.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));

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

        employees.forEach(System.out::println);


        /**
         * Comparator.comparing Use of methods
         *
         * comparing Method to receive a Function function interface, which is passed in through a lambda expression
         *
         */
        employees.sort(Comparator.comparing(e -> e.getName()));

        /**
         * This method refers to Employee::getName, which can replace lambda expression
         */
        employees.sort(Comparator.comparing(Employee::getName));

    }
}


/**
 * [Employee(name=John, age=25, salary=3000.0, mobile=9922001),
 * Employee(name=Ace, age=22, salary=2000.0, mobile=5924001),
 * Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]
 */
class Employee {
    String name;
    int age;
    double salary;
    long mobile;

    // constructors, getters & setters


    public Employee(String name, int age, double salary, long mobile) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.mobile = mobile;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public long getMobile() {
        return mobile;
    }

    public void setMobile(long mobile) {
        this.mobile = mobile;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Employee{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", salary=").append(salary);
        sb.append(", mobile=").append(mobile);
        sb.append('}');
        return sb.toString();
    }
}

 

comparing method 2

    public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

Different from the comparing method, it has an additional parameter, keyComparator, which creates a custom comparer.

Collections.sort(employees, Comparator.comparing(
                Employee::getName, (s1, s2) -> {
                    return s2.compareTo(s1);
                }));

 

Sort with Comparator.reversed

Returns the reverse collation,

/**
 *  Reverse collation
 */
Collections.sort(employees, Comparator.comparing(Employee::getName).reversed());

employees.forEach(System.out::println);

Output,

Employee{name='Keith', age=35, salary=4000.0, mobile=3924401}
Employee{name='John', age=25, salary=3000.0, mobile=9922001}
Employee{name='Ace', age=22, salary=2000.0, mobile=5924001}

 

Sort with Comparator.nullsFirst

When there is a null element in the collection, a null friendly comparer can be used, with the null element at the top of the collection

employees.add(null);  //Insert a null element
Collections.sort(employees, Comparator.nullsFirst(Comparator.comparing(Employee::getName)));
employees.forEach(System.out::println);


Collections.sort(employees, Comparator.nullsLast(Comparator.comparing(Employee::getName)));
employees.forEach(System.out::println);

 

Sorting with comparator.thencompiling

First, use name to sort, and then use ege to sort to see the effect

Collections.sort(employees, Comparator.comparing(Employee::getAge).thenComparing(Employee::getName));
employees.forEach(System.out::println);

=======END=======

Posted by Pyro on Wed, 01 Jan 2020 13:55:51 -0800