Java Comparator

By Arvind Rai, March 26, 2019
Java java.util.Comparator functional interface imposes a total ordering on collections of objects. To sort a collection we pass Comparator instance to Stream.sorted, Collections.sort, List.sort and Arrays.sort methods. Comparator can also control the order of SortedSet and the order of keys of SortedMap data structures.
The functional method of Comparator is compare(T o1, T o2) that returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. The ordering imposed by Comparator should be consistent with equals method. It is said to be consistent only if c.compare(e1, e2)==0 has the same boolean value as e1.equals(e2) for every e1 and e2 in our collection where c is instance of Comparator. Now let us discuss Comparator examples in detail.

Comparator Functional Method: compare(T o1, T o2)

compare is the functional method of Comparator functional interface. Find its declaration from Java source code.
int compare(T o1, T o2) 
compare compares its two arguments for order. It returns negative, zero or positive as the first argument is less than, equal to, or greater than the second argument. Find the examples to define compare method.

1. Define compare using Lambda Expression

We define compare functional method using lambda expression as following.
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName()); 
Find the example.
CompareDemo.java
package com.concretepage;
import java.util.Comparator;
import java.util.List;
public class CompareDemo {
  public static void main(String[] args) {
	List<Student> list = Student.getStudentList();
	
	System.out.println("--- Sort Students by age ---");
	
	Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
	list.sort(ageComp);
	list.forEach(s -> System.out.println(s));
	
	System.out.println("--- Sort Students by name ---");
	
	Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());	
	list.sort(nameComp);
	list.forEach(s -> System.out.println(s));	
  }
} 
compare functional method needs to return –ve, zero or +ve values. s1.getAge()-s2.getAge() will return either –ve or zero or +ve values. and String.compareTo compares two strings lexicographically. It returns –ve, zero or +ve values.
List.sort sorts this list according to the given Comparator instance.
Now find the Student class used in the example.
Student.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class Student implements Comparable<Student> {
  private String name;
  private int age;
  public Student(String name, int age) {
	this.name = name;
	this.age = age;
  }
  public String getName() {
	return name;
  }
  public int getAge() {
	return age;
  }
  @Override
  public int compareTo(Student s) {
	return name.compareTo(s.getName());
  }
  @Override  
  public String toString(){
	return name + "-" + age; 
  }
  public static List<Student> getStudentList(){
    Student s1 = new Student("Ram", 18);
    Student s2 = new Student("Shyam",22);
    Student s3 = new Student("Mohan",19);
    List<Student> list = Arrays.asList(s1,s2,s3);
    return list;
  }  
} 
Output
--- Sort Students by age ---
Ram-18
Mohan-19
Shyam-22
--- Sort Students by name ---
Mohan-19
Ram-18
Shyam-22 

2. Define compare implementing Comparator

CompareDemoImplement.java
package com.concretepage;
import java.io.Serializable;
import java.util.Comparator;
import java.util.List;

class AgeComparator implements Comparator<Student>, Serializable {
  private static final long serialVersionUID = 1L;
  @Override
  public int compare(Student s1, Student s2) {
     return s1.getAge() - s2.getAge();
  }
}
class NameComparator implements Comparator<Student>, Serializable {
  private static final long serialVersionUID = 1L;
  @Override
  public int compare(Student s1, Student s2) {
     return s1.getName().compareTo(s2.getName());
  }
}
public class CompareDemoImplement {
  public static void main(String[] args) {
	List<Student> list = Student.getStudentList();
	
	System.out.println("--- Sort Students by age ---");
	
	AgeComparator ageComparator = new AgeComparator();
	list.sort(ageComparator);
	list.forEach(s -> System.out.println(s));
	
	System.out.println("--- Sort Students by name ---");
	
	NameComparator nameComparator = new NameComparator();
	list.sort(nameComparator);
	list.forEach(s -> System.out.println(s));
  }
} 
Output
--- Sort Students by age ---
Ram-18
Mohan-19
Shyam-22
--- Sort Students by name ---
Mohan-19
Ram-18
Shyam-22 
It is good practice to also implement Serializable while implementing Comparator interface because they may be used as ordering methods in serializable data structures such as TreeSet and TreeMap.

Using Comparator

We can use our Comparator with Stream.sorted, Collections.sort, List.sort and Arrays.sort methods.

1. Comparator with Stream.sorted

Stream.sorted returns a stream consisting of the elements of this stream, sorted according to the provided comparator.
CompareDemoStreamSorted.java
package com.concretepage;
import java.util.Comparator;
import java.util.List;
public class CompareDemoStreamSorted {
  public static void main(String[] args) {
	List<Student> list = Student.getStudentList();
	
	System.out.println("--- Sort Students by age ---");
	
	Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
	list.stream().sorted(ageComp).forEach(s -> System.out.println(s));
	
	System.out.println("--- Sort Students by name ---");
	
	Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());	
	list.stream().sorted(nameComp).forEach(s -> System.out.println(s));	
  }
} 
Use Student class from compare example above on this page.

2. Comparator with Collections.sort

Collections.sort sorts the specified list according to the given Comparator instance.
CompareDemoCollectionsSort.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CompareDemoCollectionsSort {
  public static void main(String[] args) {
	List<Student> list = Student.getStudentList();
	
	System.out.println("--- Sort Students by age ---");
	
	Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
	Collections.sort(list, ageComp);
	list.forEach(s -> System.out.println(s));
	
	System.out.println("--- Sort Students by name ---");
	
	Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());	
	Collections.sort(list, nameComp);
	list.forEach(s -> System.out.println(s));	
  }
} 
Use Student class from compare example above on this page.

3. Comparator with List.sort

List.sort sorts this list according to the given Comparator instance.
CompareDemoListSort.java
package com.concretepage;
import java.util.Comparator;
import java.util.List;
public class CompareDemoListSort {
  public static void main(String[] args) {
	List<Student> list = Student.getStudentList();
	
	System.out.println("--- Sort Students by age ---");
	
	Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
	list.sort(ageComp);
	list.forEach(s -> System.out.println(s));
	
	System.out.println("--- Sort Students by name ---");
	
	Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());	
	list.sort(nameComp);
	list.forEach(s -> System.out.println(s));	
  }
} 
Use Student class from compare example above on this page.

4. Comparator with Arrays.sort

Arrays.sort sorts the specified array of objects according to the order induced by the specified comparator.
CompareDemoArraysSort.java
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
public class CompareDemoArraysSort {
  public static void main(String[] args) {
        Student st1 = new Student("Ram", 18);
        Student st2 = new Student("Shyam",22);
        Student st3 = new Student("Mohan",19);
    
	Student[] array = {st1, st2, st3};
	
	System.out.println("--- Sort Students by age ---");
	
	Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
	Arrays.sort(array, ageComp);
	for (Student s : array) {
	  System.out.println(s);
	}
	
	System.out.println("--- Sort Students by name ---");
	
	Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());	
	Arrays.sort(array, nameComp);
	for (Student s : array) {
	  System.out.println(s);
	}
  }
} 
Use Student class from compare example above on this page.

Comparator Methods

In Java 8, Comparator interface has introduced some static and defaults methods. Here we will discuss these methods with examples. We can use Comparator with Stream.sorted, List.sort, Collections.sort and Arrays.sort to sort the collections and maps.

1. reversed

reversed is the default method of Java Comparator functional interface. reversed returns a Comparator that imposes the reverse ordering of this Comparator. It has been declared as following.
default Comparator<T> reversed() 
To use reversed method, we need to instantiate our Comparator and call this method. reversed will return new instance of Comparator that will impose the reverse ordering of this comparator. Find the sample code to use this method.
Comparator<Student> nameComparator = (s1, s2) -> s1.getName().compareTo(s2.getName());
Collections.sort(list, nameComparator.reversed()); 
Find the reversed example with Stream.sorted method. Use Student class from compare example above on this page.
ComparatorReversedDemo.java
package com.concretepage;
import java.util.Comparator;
import java.util.List;
import com.concretepage.Student;
public class ComparatorReversedDemo {
  public static void main(String[] args) {
	List<Student> list = Student.getStudentList();
	Comparator<Student> ageComparator = (s1, s2) -> s1.getAge() - s2.getAge();	
	list.stream().sorted(ageComparator.reversed()).forEach(s -> System.out.print(s.getAge() + " "));
	System.out.println("\n-----------");
	Comparator<Student> nameComparator = (s1, s2) -> s1.getName().compareTo(s2.getName());	
	list.stream().sorted(nameComparator.reversed()).forEach(s -> System.out.print(s.getName() + " "));
	System.out.println("\n-----------");	
	list.stream().sorted(Comparator.comparing(Student::getAge).reversed()).forEach(s -> System.out.print(s.getAge() + " "));
	System.out.println("\n-----------");
	list.stream().sorted(Comparator.comparing(Student::getName).reversed()).forEach(s -> System.out.print(s.getName() + " "));	
  }
} 
Output
22 19 18 
-----------
Shyam Ram Mohan 
-----------
22 19 18 
-----------
Shyam Ram Mohan 

2. reverseOrder

reverseOrder is a static method that returns Comparator to imposes sorting in reverse natural ordering of collection of objects. For natural ordering, a class needs to implement Comparable and define compareTo method. A collection of objects are sorted according to compareTo in natural ordering. Comparator.reverseOrder reverses the natural ordering. It calls Collections.reverseOrder() internally and returns Comparator instance. Find the Java source code for Comparator.reverseOrder.
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
     return Collections.reverseOrder();
} 
Find the example with Collections.sort method. Use Student class from compare example above on this page.
ComparatorReverseOrderDemo.java
package com.concretepage;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparatorReverseOrderDemo {
  public static void main(String[] args) {
	List<Integer> numList = Arrays.asList(12, 10, 15, 8, 11);
	Collections.sort(numList, Comparator.reverseOrder());
	numList.forEach(n -> System.out.print(n + " "));
	System.out.println("\n-----------");
	
	List<String> strList = Arrays.asList("Varanasi", "Allahabad", "Kanpur", "Noida");
	Collections.sort(strList, Comparator.reverseOrder());
	strList.forEach(s -> System.out.print(s + " "));
	System.out.println("\n-----------");	
	
	List<Student> stdList = Student.getStudentList();
	Collections.sort(stdList, Comparator.reverseOrder());
	stdList.forEach(s -> System.out.print(s.getName() + " "));	
  }
} 
Output
15 12 11 10 8 
-----------
Varanasi Noida Kanpur Allahabad 
-----------
Shyam Ram Mohan 

3. naturalOrder

naturalOrder is the static method of Comparator functional interface. Comparator.naturalOrder method returns a comparator that compares Comparable objects in natural order. For natural ordering, a class needs to implement Comparable and define compareTo method. A collection of objects are sorted according to compareTo method in natural ordering. Java classes such as Integer, String and Date implement Comparable interface and override its compareTo method and they are sorted in lexicographic-order.
Find the naturalOrder method declaration from Java source code.
static <T extends Comparable<? super T>> Comparator<T> naturalOrder() 
Find the example of Comparator.naturalOrder using List.sort method. Use Student class from compare example above on this page.
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class ComparatorNaturalOrderDemo {
  public static void main(String[] args) {
	List<Integer> numList = Arrays.asList(12, 10, 15, 8, 11);
	numList.sort(Comparator.naturalOrder());
	numList.forEach(n -> System.out.print(n + " "));
	System.out.println("\n-----------");
	
	List<String> strList = Arrays.asList("Varanasi", "Allahabad", "Kanpur", "Noida");
	strList.sort(Comparator.naturalOrder());
	strList.forEach(s -> System.out.print(s + " "));
	System.out.println("\n-----------");	
	
	List<Student> stdList = Student.getStudentList();
	stdList.sort(Comparator.naturalOrder());
	stdList.forEach(s -> System.out.print(s.getName() + " "));
  }
} 
Output
8 10 11 12 15 
-----------
Allahabad Kanpur Noida Varanasi 
-----------
Mohan Ram Shyam 

4. nullsFirst

nullsFirst is the static method of Comparator functional interface. Comparator.nullsFirst method returns a null-friendly comparator that considers null to be less than non-null. Find its declaration from Java source code.
static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) 
Find the working of the comparator returned by nullsFirst method.
1. The null element is considered to be less than non-null.
2. When both elements are null, then they are considered equal.
3. When both elements are non-null, the specified Comparator determines the order.
4. If specified comparator is null, then the returned comparator considers all non-null elements equal.

Find the example. Use Student class from compare example above on this page.
NullsFirstDemo.java
package com.concretepage;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class NullsFirstDemo {
  public static void main(String[] args) {
	Student s1 = new Student("Ram", 18);
	Student s2 = new Student("Shyam", 22);
	Student s3 = new Student("Mohan", 17);

	System.out.println("-------Case1: One null----------");

	List<Student> list = Arrays.asList(s1, s2, null, s3);
	Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case2: More than one null---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case3: Reverse specified Comparator to nullsFirst---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName).reversed()));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case4: Reverse Comparator returned by nullsFirst---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)).reversed());
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case5: Specify natural order Comparator to nullsFirst---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsFirst(Comparator.naturalOrder()));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case6: Specify null to nullsFirst---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsFirst(null));
	list.forEach(s -> System.out.println(s));
  }
}
Output
-------Case1: One null----------
null
Mohan-17
Ram-18
Shyam-22
--------Case2: More than one null---------
null
null
Mohan-17
Ram-18
Shyam-22
--------Case3: Reverse specified Comparator to nullsFirst---------
null
null
Shyam-22
Ram-18
Mohan-17
--------Case4: Reverse Comparator returned by nullsFirst---------
Shyam-22
Ram-18
Mohan-17
null
null
--------Case5: Specify natural order Comparator to nullsFirst---------
null
null
Mohan-17
Ram-18
Shyam-22
--------Case6: Specify null to nullsFirst---------
null
null
Ram-18
Shyam-22
Mohan-17 

5. nullsLast

nullsLast is the static method of Comparator functional interface. Comparator.nullsLast method returns a null-friendly comparator that considers null to be greater than non-null. Find its declaration from Java source code.
static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) 
Find the working of the comparator returned by nullsLast method.
1. The null element is considered to be greater than non-null.
2. When both elements are null, then they are considered equal.
3. When both elements are non-null, the specified Comparator determines the order.
4. If specified comparator is null, then the returned comparator considers all non-null elements equal.

Find the example. Use Student class from compare example above on this page.
NullsLastDemo.java
package com.concretepage;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class NullsLastDemo {
  public static void main(String[] args) {
	Student s1 = new Student("Ram", 18);
	Student s2 = new Student("Shyam", 22);
	Student s3 = new Student("Mohan", 17);

	System.out.println("-------Case1: One null----------");

	List<Student> list = Arrays.asList(s1, s2, null, s3);
	Collections.sort(list, Comparator.nullsLast(Comparator.comparing(Student::getName)));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case2: More than one null---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsLast(Comparator.comparing(Student::getName)));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case3: Reverse specified Comparator to nullsLast---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsLast(Comparator.comparing(Student::getName).reversed()));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case4: Reverse Comparator returned by nullsLast---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsLast(Comparator.comparing(Student::getName)).reversed());
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case5: Specify natural order Comparator to nullsLast---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsLast(Comparator.naturalOrder()));
	list.forEach(s -> System.out.println(s));

	System.out.println("--------Case6: Specify null to nullsLast---------");

	list = Arrays.asList(s1, null, s2, null, s3);
	Collections.sort(list, Comparator.nullsLast(null));
	list.forEach(s -> System.out.println(s));
  }
} 
Output
-------Case1: One null----------
Mohan-17
Ram-18
Shyam-22
null
--------Case2: More than one null---------
Mohan-17
Ram-18
Shyam-22
null
null
--------Case3: Reverse specified Comparator to nullsLast---------
Shyam-22
Ram-18
Mohan-17
null
null
--------Case4: Reverse Comparator returned by nullsLast---------
null
null
Shyam-22
Ram-18
Mohan-17
--------Case5: Specify natural order Comparator to nullsLast---------
Mohan-17
Ram-18
Shyam-22
null
null
--------Case6: Specify null to nullsLast---------
Ram-18
Shyam-22
Mohan-17
null
null 

6. comparing

comparing is the static method of Comparator functional interface. Comparator.comparing accepts a Function that extracts a Comparable sort key from the given type and returns a Comparator that compares by that sort key. Comparator.comparing has two forms.
1.
static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor) 
We need to pass a Function and it will extract a Comparable sort key from a type T, and will return a Comparator that compares by that sort key. Find the sample code.
Comparator<Student> nameComparator = Comparator.comparing(Student::getName); 
2.
static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator) 
We need to pass a Function and a Comparator. The method will extract a sort key from a type T, and returns a Comparator that compares by that sort key using the specified Comparator. Find the sample code.
Comparator<Student> nameComparator = Comparator.comparing(Student::getName, (s1, s2) -> s2.compareTo(s1)); 
For the int, long and double datatype sort keys, Comparator has comparingInt, comparingLong and comparingDouble methods respectively.
Here we will provide the examples of Comparator.comparing method. Find a class that will implement Comparable interface and define compareTo method.
School.java
package com.concretepage;
public class School implements Comparable<School> {
  private int code;
  private String sname;
  public School(int code, String sname) {
	this.code = code;
	this.sname = sname;
  }
  public int getCode() {
        return code;
  }
  public String getSname() {
        return sname;
  }
  @Override
  public int compareTo(School s) {
	return s.sname.compareTo(sname);
  }
} 
Create another class in which we will create class property of School type.
Student.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class Student {
  private String name;
  private int age;
  private long homeDistance;  
  private double weight;
  private School school;
  public Student(String name, int age, long homeDistance, double weight, School school) {
	this.name = name;
	this.age = age;
	this.homeDistance = homeDistance;
	this.weight = weight;
	this.school = school;
  }
  public String getName() {
        return name;
  }
  public int getAge() {
        return age;
  }
  public long getHomeDistance() {
        return homeDistance;
  }
  public double getWeight() {
        return weight;
  }
  public School getSchool() {
        return school;
  }
  public static List<Student> getStudentList() {
	Student s1 = new Student("Ram", 18, 3455, 60.75, new School(101, "PQ College"));
	Student s2 = new Student("Shyam", 22, 3252, 65.80, new School(103, "RS College"));
	Student s3 = new Student("Mohan", 19, 1459, 65.20, new School(102, "AB College"));
	Student s4 = new Student("Mahesh", 20, 4450, 70.25, new School(104, "CD College"));
	List<Student> list = Arrays.asList(s1, s2, s3, s4);
	return list;
  }
} 
Now find the example of Comparator.comparing method.
ComparingDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparingDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Comparator<Student> schoolComparator1 = Comparator.comparing(Student::getSchool);
    Collections.sort(list, schoolComparator1);
    list.forEach(s->System.out.print(s.getName() + "-" + s.getSchool().getSname() + " | "));
    System.out.println("\n-------------------");    
    
    Comparator<Student> schoolComparator2 = 
    	Comparator.comparing(Student::getSchool, (sch1, sch2) -> sch1.getCode() - sch2.getCode());
    Collections.sort(list, schoolComparator2);
    list.forEach(s->System.out.print(s.getName() + "-" + s.getSchool().getCode() + " | "));
    System.out.println("\n-------------------");    
    
    Comparator<Student> nameComparator1 = Comparator.comparing(Student::getName); 
    Collections.sort(list, nameComparator1);
    list.forEach(s->System.out.print(s.getName() + " "));
    System.out.println("\n-------------------");

    Comparator<Student> nameComparator2 = Comparator.comparing(Student::getName, (s1, s2) -> s2.compareTo(s1));     
    Collections.sort(list, nameComparator2);
    list.forEach(s->System.out.print(s.getName() + " "));    
  }
} 
Output
Shyam-RS College | Ram-PQ College | Mahesh-CD College | Mohan-AB College | 
-------------------
Ram-101 | Mohan-102 | Shyam-103 | Mahesh-104 | 
-------------------
Mahesh Mohan Ram Shyam 
-------------------
Shyam Ram Mohan Mahesh 

7. comparingInt

Find the declaration of comparingInt method.
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) 
It accepts a function that extracts an int sort key from a type T, and returns a Comparator that compares by that sort key. Find the example. Use Student class from comparing example above on this page.
ComparingIntDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparingIntDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Collections.sort(list, Comparator.comparingInt(Student::getAge));
    list.forEach(s->System.out.print(s.getAge() + " "));    
  }
} 
Output
18 19 20 22 

8. comparingLong

Find the declaration of comparingLong method.
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) 
It accepts a function that extracts a long sort key from a type T, and returns a Comparator that compares by that sort key. Find the example. Use Student class from comparing example above on this page.
ComparingLongDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparingLongDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Collections.sort(list, Comparator.comparingLong(Student::getHomeDistance));
    list.forEach(s->System.out.print(s.getHomeDistance() + " "));           
  }
} 
Output
1459 3252 3455 4450 

9. comparingDouble

Find the declaration of comparingDouble method.
static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) 
It accepts a function that extracts a double sort key from a type T, and returns a Comparator that compares by that sort key. Find the example. Use Student class from comparing example above on this page.
ComparingDoubleDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparingDoubleDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Collections.sort(list, Comparator.comparingDouble(Student::getWeight));
    list.forEach(s->System.out.print(s.getWeight() + " "));           
  }
}
Output
60.75 65.2 65.8 70.25 

10. thenComparing

thenComparing is the default method of Comparator functional interface. Comparator.thenComparing returns a lexicographic-order comparator that is called by a Comparator instance to sort the items using group of sort keys. When this comparator compares two elements equal then thenComparing method determines the order. We can use Comparator.thenComparing multiple times. It is useful when we want to determine the order of elements by the group of sort keys. For the int, long and double datatype sort keys, Comparator has thenComparingInt, thenComparingLong and thenComparingDouble default methods respectively.
thenComparing has following forms.
1.
default Comparator<T> thenComparing(Comparator<? super T> other) 
It returns a lexicographic-order comparator with another comparator. Find the code snippet.
Comparator<Student> compByStdName = Comparator.comparing(Student::getName);
Comparator<Student> schoolComparator1 = Comparator.comparing(Student::getAge) //sort by student age
	.thenComparing(compByStdName); //then sort by student name 
First the comparator will sort the collections of Student by student age and if for some student, there are equal age then it will be sorted by their name.
2.
default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor) 
It returns a lexicographic-order comparator with a function that extracts a Comparable sort key. Find the code snippet.
Comparator<Student> schoolComparator2 = Comparator.comparing(Student::getSchool) //sort by school natural ordering i.e. city
	.thenComparing(Student::getAge) //then sort by student age
	.thenComparing(Student::getName); //then sort by student name 
First the collections of Student will be sorted by their respective School with its natural order and if some students are equal according to their School ordering then those students will be sorted by their respective age and if ages are also equals then they will be sorted by their name.
3.
default <U> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator) 
It returns a lexicographic-order comparator with a function that extracts a key to be compared with the given Comparator. Find the code snippet.
Comparator<Student> schoolComparator3 = Comparator.comparing(Student::getSchool) //sort by school natural ordering i.e. city
	.thenComparing(Student::getSchool, (school1, school2) -> school1.getSname().compareTo(school2.getSname())) //then sort by school name 
	.thenComparing(Student::getAge) //then sort by student age
	.thenComparing(Student::getName); //then sort by student name 
First the collections of Student will be sorted by their respective School with its natural order (i.e. by school city in our demo) then if the students are with same school city, they will be sorted by their respective school name and if the students are with same school name, they will be sorted by their age and if the students are with same age, they will be sorted by their name.

Now find the complete example.
School.java
package com.concretepage;
public class School implements Comparable<School> {
  private String sname;
  private String city;  
  public School(String sname, String city) {
	this.sname = sname;
	this.city = city;
  }
  public String getSname() {
        return sname;
  }
  public String getCity() {
        return city;
  }
  @Override
  public int compareTo(School s) {
	return s.getCity().compareTo(city);
  }
} 
Student.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class Student {
  private String name;
  private int age;
  private long homeDistance;
  private double weight;
  private School school;

  public Student(String name, int age, long homeDistance, double weight, School school) {
	this.name = name;
	this.age = age;
	this.homeDistance = homeDistance;
	this.weight = weight;
	this.school = school;
  }
  public String getName() {
	return name;
  }
  public int getAge() {
	return age;
  }
  public long getHomeDistance() {
	return homeDistance;
  }
  public double getWeight() {
	return weight;
  }
  public School getSchool() {
	return school;
  }
  public static List<Student> getStudentList() {
	Student s1 = new Student("Ram", 18, 3455, 60.75, new School("AB College", "Noida"));
	Student s2 = new Student("Shyam", 22, 3252, 65.80, new School("RS College", "Gurugram"));
	Student s3 = new Student("Mohan", 18, 1459, 65.20, new School("AB College", "Noida"));
	Student s4 = new Student("Mahesh", 22, 4450, 70.25, new School("RS College", "Gurugram"));
	List<Student> list = Arrays.asList(s1, s2, s3, s4);
	return list;
  }
} 
ThenComparingDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ThenComparingDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    System.out.println("--------Example-1---------"); 
    
    Comparator<Student> compByStdName = Comparator.comparing(Student::getName);
    Comparator<Student> schoolComparator1 = Comparator.comparing(Student::getAge) //sort by student age
    	.thenComparing(compByStdName); //then sort by student name   
    
    Collections.sort(list, schoolComparator1);
    list.forEach(s->System.out.println(s.getName() + "-" + s.getAge()));
    
    System.out.println("--------Example-2---------");   
    
    Comparator<Student> schoolComparator2 = Comparator.comparing(Student::getSchool) //sort by school natural ordering i.e. city
    	.thenComparing(Student::getAge) //then sort by student age
    	.thenComparing(Student::getName); //then sort by student name   
    
    Collections.sort(list, schoolComparator2);
    list.forEach(s->System.out.println(s.getName() + "-" + s.getAge()+ "-" + s.getSchool().getCity()));
    
    System.out.println("--------Example-3---------");    
    
    Comparator<Student> schoolComparator3 = Comparator.comparing(Student::getSchool) //sort by school natural ordering i.e. city
    	.thenComparing(Student::getSchool, (school1, school2) -> school1.getSname().compareTo(school2.getSname())) //then sort by school name 
    	.thenComparing(Student::getAge) //then sort by student age
    	.thenComparing(Student::getName); //then sort by student name 
    
    Collections.sort(list, schoolComparator3);
    list.forEach(s->System.out.println(s.getName() + "-" + s.getAge()+ "-" + s.getSchool().getSname() + "-" + s.getSchool().getCity()));
  }
} 
Output
--------Example-1---------
Mohan-18
Ram-18
Mahesh-22
Shyam-22
--------Example-2---------
Mohan-18-Noida
Ram-18-Noida
Mahesh-22-Gurugram
Shyam-22-Gurugram
--------Example-3---------
Mohan-18-AB College-Noida
Ram-18-AB College-Noida
Mahesh-22-RS College-Gurugram
Shyam-22-RS College-Gurugram 

11. thenComparingInt

Find the thenComparingInt method declaration.
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) 
It returns a lexicographic-order comparator with a function that extracts an int sort key. Find the example. Use Student class from thenComparing example above on this page.
ThenComparingIntDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ThenComparingIntDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Comparator<Student> comparator = Comparator.comparing(Student::getName, (s1, s2) -> s1.charAt(0) - s2.charAt(0))
    	.thenComparingInt(Student::getAge);
    
    Collections.sort(list, comparator);
    list.forEach(s->System.out.println(s.getName() + "-" + s.getAge()));    
  }
} 
Output
Mohan-18
Mahesh-22
Ram-18
Shyam-22 

12. thenComparingLong

Find the thenComparingLong method declaration.
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) 
It returns a lexicographic-order comparator with a function that extracts a long sort key. Find the example. Use Student class from thenComparing example above on this page.
ThenComparingLongDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ThenComparingLongDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Comparator<Student> comparator = Comparator.comparing(Student::getName, (s1, s2) -> s1.charAt(0) - s2.charAt(0))
    	.thenComparingLong(Student::getHomeDistance);
    
    Collections.sort(list, comparator);
    list.forEach(s->System.out.println(s.getName() + "-" + s.getHomeDistance()));  
  }
} 
Output
Mohan-1459
Mahesh-4450
Ram-3455
Shyam-3252 

13. thenComparingDouble

Find the thenComparingDouble method declaration.
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) 
It returns a lexicographic-order comparator with a function that extracts a double sort key. Find the example. Use Student class from thenComparing example above on this page.
ThenComparingDoubleDemo.java
package com.concretepage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ThenComparingDoubleDemo {
  public static void main(String[] args) {
    List<Student> list = Student.getStudentList();
    
    Comparator<Student> comparator = Comparator.comparing(Student::getName, (s1, s2) -> s1.charAt(0) - s2.charAt(0))
    	.thenComparingDouble(Student::getWeight);
    
    Collections.sort(list, comparator);
    list.forEach(s->System.out.println(s.getName() + "-" + s.getWeight()));         
  }
} 
Output
Mohan-65.2
Mahesh-70.25
Ram-60.75
Shyam-65.8 

Comparator with SortedSet

Java Comparator can be used to control the order of SortedSet data structures. The implementing classes of SortedSet are TreeSet and ConcurrentSkipListSet. We can pass Comparator instance to the constructor of TreeSet and ConcurrentSkipListSet classes to control its order. SortedSet provides comparator() method that returns the comparator used to order the elements in this set. If SortedSet uses natural ordering of its elements, then comparator() method returns null. Here on this page we will provide examples to use comparator with TreeSet and ConcurrentSkipListSet classes.
1. Comparator with TreeSet
TreeSet orders the elements according to their natural ordering, or by a comparator provided at set creation time, depending on which constructor is used. We can instantiate TreeSet class by passing Comparator using following constructor.
TreeSet(Comparator<? super E> comparator) 
It constructs a new, empty tree set, sorted according to the specified comparator. When we don’t pass comparator, TreeSet sorts the elements according to its natural ordering. For natural ordering, a class needs to implement Comparable interface and override compareTo method.
To get the comparator used by our TreeSet object, SortedSet provides comparator() method.
Now find the example using comparator with TreeSet class to control the order of its elements. Use Student class from compare example above on this page.
TreeSetDemo.java
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo {
  public static void main(String[] args) {
	Student s1 = new Student("Shyam", 18);
	Student s2 = new Student("Mohan", 20);
	Student s3 = new Student("Ram", 22);
	
	System.out.println("---TreeSet Order With Comparator---");
	
	Comparator<Student> ageComparator = Comparator.comparing(Student::getAge);
	TreeSet<Student> myTreeSet = new TreeSet<>(ageComparator);
	myTreeSet.addAll(Arrays.asList(s1, s2, s3));
	myTreeSet.forEach(s -> System.out.println(s));	
	//System.out.println("Comparator: "+ myTreeSet.comparator());
	
	System.out.println("---TreeSet Natural Order (With Comparable)---");
	
	myTreeSet = new TreeSet<>();
	myTreeSet.addAll(Arrays.asList(s1, s2, s3));
	myTreeSet.forEach(s -> System.out.println(s));
  }
} 
Output
---TreeSet Order With Comparator---
Shyam-18
Mohan-20
Ram-22
---TreeSet Natural Order (With Comparable)---
Mohan-20
Ram-22
Shyam-18 
2. Comparator with ConcurrentSkipListSet
ConcurrentSkipListSet orders the elements according to their natural ordering, or by a comparator provided at set creation time, depending on which constructor is used. We can instantiate ConcurrentSkipListSet class by passing Comparator using following constructor.
ConcurrentSkipListSet(Comparator<? super E> comparator) 
It constructs a new, empty set that orders its elements according to the specified comparator. When we don’t pass comparator, ConcurrentSkipListSet sorts the elements according to its natural ordering. For natural ordering, a class needs to implement Comparable interface and override compareTo method.
To get the comparator used by our ConcurrentSkipListSet object, SortedSet provides comparator() method.
Now find the example using comparator with ConcurrentSkipListSet class to control the order of its elements.
ConcurrentSkipListSetDemo.java
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.concurrent.ConcurrentSkipListSet;
public class ConcurrentSkipListSetDemo {
  public static void main(String[] args) {
	Student s1 = new Student("Shyam", 18);
	Student s2 = new Student("Mohan", 20);
	Student s3 = new Student("Ram", 22);
	
	System.out.println("---ConcurrentSkipListSet Order With Comparator---");
	
	Comparator<Student> ageComparator = Comparator.comparing(Student::getAge);
	ConcurrentSkipListSet<Student> myConcurrentSkipList = new ConcurrentSkipListSet<>(ageComparator);
	myConcurrentSkipList.addAll(Arrays.asList(s1, s2, s3));
	myConcurrentSkipList.forEach(s -> System.out.println(s));	
	//System.out.println("Comparator: "+ myConcurrentSkipList.comparator());
	
	System.out.println("---ConcurrentSkipListSet Natural Order (With Comparable)---");
	
	myConcurrentSkipList = new ConcurrentSkipListSet<>();
	myConcurrentSkipList.addAll(Arrays.asList(s1, s2, s3));
	myConcurrentSkipList.forEach(s -> System.out.println(s));
  }
}
Output
---ConcurrentSkipListSet Order With Comparator---
Shyam-18
Mohan-20
Ram-22
---ConcurrentSkipListSet Natural Order (With Comparable)---
Mohan-20
Ram-22
Shyam-18 

Comparator with SortedMap

Java Comparator can be used to control the order of keys of SortedMap data structures. The implementing classes of SortedMap are TreeMap and ConcurrentSkipListMap. We can pass Comparator instance to the constructor of TreeMap and ConcurrentSkipListMap classes to control the order of its keys. SortedMap provides comparator() method that returns the comparator used to order the keys in this map. If SortedMap uses natural ordering of key elements, then comparator() method returns null. Here on this page we will provide examples to use comparator with TreeMap and ConcurrentSkipListMap classes.
1. Comparator with TreeMap
TreeMap are sorted according to the natural ordering of its keys, or by a comparator provided at map creation time, depending on which constructor is used. We can instantiate TreeMap class by passing Comparator using following constructor.
TreeMap(Comparator<? super K> comparator) 
It constructs a new, empty tree map, ordered according to the given comparator. When we don’t pass comparator, TreeMap sorts keys to its natural ordering. For natural ordering, an element class needs to implement Comparable interface and override compareTo method.
To get the comparator used by our TreeMap object, SortedMap provides comparator() method.
Now find the example using comparator with TreeMap class to control the order of its keys. Use Student class from compare example above on this page.
TreeMapDemo.java
package com.concretepage;
import java.util.Comparator;
import java.util.TreeMap;
public class TreeMapDemo {
  public static void main(String[] args) {
	Student s1 = new Student("Shyam", 18);
	Student s2 = new Student("Mohan", 20);
	Student s3 = new Student("Ram", 22);
	
	System.out.println("---TreeMap Order With Comparator---");
	
	Comparator<Student> ageComparator = Comparator.comparing(Student::getAge);
	TreeMap<Student, String> myTreeMap = new TreeMap<>(ageComparator);
	myTreeMap.put(s1, "Varanasi");
	myTreeMap.put(s2, "Mathura");
	myTreeMap.put(s3, "Kashi");	
	myTreeMap.forEach((k, v) -> System.out.println(k + " - " + v));	
	//System.out.println("Comparator: "+ myTreeMap.comparator());
	
	System.out.println("---TreeMap Natural Order (With Comparable)---");
	
	myTreeMap = new TreeMap<>();
	myTreeMap.put(s1, "Varanasi");
	myTreeMap.put(s2, "Mathura");
	myTreeMap.put(s3, "Kashi");	
	myTreeMap.forEach((k, v) -> System.out.println(k + " - " + v));	
  }
} 
Output
---TreeMap Order With Comparator---
Shyam-18 - Varanasi
Mohan-20 - Mathura
Ram-22 - Kashi
---TreeMap Natural Order (With Comparable)---
Mohan-20 - Mathura
Ram-22 - Kashi
Shyam-18 - Varanasi 
2. Comparator with ConcurrentSkipListMap
ConcurrentSkipListMap are sorted according to the natural ordering of its keys, or by a comparator provided at map creation time, depending on which constructor is used. We can instantiate ConcurrentSkipListMap class by passing Comparator using following constructor.
ConcurrentSkipListMap(Comparator<? super K> comparator) 
It constructs a new, empty map, ordered according to the given comparator. When we don’t pass comparator, ConcurrentSkipListMap sorts keys to its natural ordering. For natural ordering, an element class needs to implement Comparable interface and override compareTo method.
To get the comparator used by our ConcurrentSkipListMap object, SortedMap provides comparator() method.
Now find the example using comparator with ConcurrentSkipListMap class to control the order of its keys.
ConcurrentSkipListMapDemo.java
package com.concretepage;
import java.util.Comparator;
import java.util.concurrent.ConcurrentSkipListMap;
public class ConcurrentSkipListMapDemo {
  public static void main(String[] args) {
	Student s1 = new Student("Shyam", 18);
	Student s2 = new Student("Mohan", 20);
	Student s3 = new Student("Ram", 22);
	
	System.out.println("---ConcurrentSkipListMap Order With Comparator---");
	
	Comparator<Student> ageComparator = Comparator.comparing(Student::getAge);
	ConcurrentSkipListMap<Student, String> myConcurrentSkipListMap = new ConcurrentSkipListMap<>(ageComparator);
	myConcurrentSkipListMap.put(s1, "Varanasi");
	myConcurrentSkipListMap.put(s2, "Mathura");
	myConcurrentSkipListMap.put(s3, "Kashi");	
	myConcurrentSkipListMap.forEach((k, v) -> System.out.println(k + " - " + v));	
	//System.out.println("Comparator: "+ myConcurrentSkipListMap.comparator());
	
	System.out.println("---ConcurrentSkipListMap Natural Order (With Comparable)---");
	
	myConcurrentSkipListMap = new ConcurrentSkipListMap<>();
	myConcurrentSkipListMap.put(s1, "Varanasi");
	myConcurrentSkipListMap.put(s2, "Mathura");
	myConcurrentSkipListMap.put(s3, "Kashi");	
	myConcurrentSkipListMap.forEach((k, v) -> System.out.println(k + " - " + v));	
  }
} 
Output
---ConcurrentSkipListMap Order With Comparator---
Shyam-18 - Varanasi
Mohan-20 - Mathura
Ram-22 - Kashi
---ConcurrentSkipListMap Natural Order (With Comparable)---
Mohan-20 - Mathura
Ram-22 - Kashi
Shyam-18 - Varanasi 

References

Interface Comparator
Interface SortedSet
Interface SortedMap
POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us