Java Comparator
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.
Contents
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());
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; } }
--- 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)); } }
--- Sort Students by age --- Ram-18 Mohan-19 Shyam-22 --- Sort Students by name --- Mohan-19 Ram-18 Shyam-22
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 ourComparator
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)); } }
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)); } }
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)); } }
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); } } }
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()
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());
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() + " ")); } }
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(); }
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() + " ")); } }
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()
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() + " ")); } }
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)
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)); } }
-------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)
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)); } }
-------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)
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);
static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)
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));
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); } }
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; } }
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() + " ")); } }
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 ofcomparingInt
method.
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
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() + " ")); } }
18 19 20 22
8. comparingLong
Find the declaration ofcomparingLong
method.
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
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() + " ")); } }
1459 3252 3455 4450
9. comparingDouble
Find the declaration ofcomparingDouble
method.
static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
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() + " ")); } }
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)
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
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)
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
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)
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
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); } }
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; } }
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())); } }
--------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 thethenComparingInt
method declaration.
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)
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())); } }
Mohan-18 Mahesh-22 Ram-18 Shyam-22
12. thenComparingLong
Find thethenComparingLong
method declaration.
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor)
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())); } }
Mohan-1459 Mahesh-4450 Ram-3455 Shyam-3252
13. thenComparingDouble
Find thethenComparingDouble
method declaration.
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)
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())); } }
Mohan-65.2 Mahesh-70.25 Ram-60.75 Shyam-65.8
Comparator with SortedSet
JavaComparator
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)
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)); } }
---TreeSet Order With Comparator--- Shyam-18 Mohan-20 Ram-22 ---TreeSet Natural Order (With Comparable)--- Mohan-20 Ram-22 Shyam-18
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)
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)); } }
---ConcurrentSkipListSet Order With Comparator--- Shyam-18 Mohan-20 Ram-22 ---ConcurrentSkipListSet Natural Order (With Comparable)--- Mohan-20 Ram-22 Shyam-18
Comparator with SortedMap
JavaComparator
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)
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)); } }
---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
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)
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)); } }
---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 ComparatorInterface SortedSet
Interface SortedMap