Chapters
Comparator is a comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order. Comparators can also be used to control the order of certain data structures (such as sorted sets or sorted maps), or to provide an ordering for collections of objects that don't have a natural ordering.
The ordering imposed by a comparator
Caution should be exercised when using a comparator capable of imposing an ordering inconsistent with equals to order a sorted set (or sorted map). Suppose a sorted set (or sorted map) with an explicit comparator
Unlike Comparable, a comparator may optionally permit comparison of null arguments. This interface is a member of the Java Collections Framework.
To implement our own Comparator, we need to override the Comparator's compare() method.
If you're planning to create a sorting algorithm from scratch, you should read the compare() description in the documentation.
Comparator has several methods that we can use. I'll demonstrate some of them here. If you wanna see all Comparator's method, go to the Comparator documentation. You need to be knowledgeable about generics and lambda expression to understand the syntax of the methods that I'm gonna explain in this chapter.
This method accepts a function that extracts a Comparable sort key from a type T, and returns a Comparator<T> that compares by that sort key.
This method has two forms. In this topic, I'm gonna demonstrate this one:
The parameter here is a method reference with return type. The Comparable sort key will be extracted from the input and the output is a Comparator with sort key extracted from the input. Comparable sort key is a key that we can get from objects that implement Comparable. In this method, this key helps us sort an input from a method reference.
Method Forms:
This example demonstrates
The first form:
Returns a lexicographic-order comparator with another comparator. If this(caller) Comparator considers two elements equal, i.e. compare(a, b) == 0, other(parameter) is used to determine the order. The returned comparator is serializable if the specified comparator is also serializable.
The "other" comparator copies that comparison pattern from compareTo() of String. compareTo() is case sensitive. Thus, "Allen Green" moved up and "allen Green" moved down because
Comparator
Comparator is a comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order. Comparators can also be used to control the order of certain data structures (such as sorted sets or sorted maps), or to provide an ordering for collections of objects that don't have a natural ordering.
The ordering imposed by a comparator
c
on a set of elements S
is said to be consistent with equals if and only if c.compare(e1, e2)==0
has the same boolean value as e1.equals(e2)
for every e1
and e2
in S
.
Caution should be exercised when using a comparator capable of imposing an ordering inconsistent with equals to order a sorted set (or sorted map). Suppose a sorted set (or sorted map) with an explicit comparator
c
is used with elements (or keys) drawn from a set S
. If the ordering imposed by c
on S
is inconsistent with equals, the sorted set (or sorted map) will behave "strangely." In particular the sorted set (or sorted map) will violate the general contract for set (or map), which is defined in terms of equals.
Unlike Comparable, a comparator may optionally permit comparison of null arguments. This interface is a member of the Java Collections Framework.
Implementing Comparator
To implement our own Comparator, we need to override the Comparator's compare() method.
import java.util.Comparator; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.io.IOException; public class SampleClass{ public static void main(String[] args) throws IOException{ ArrayList<File> files = new ArrayList<>(); files.add(new File("F:\\name1\\eddie")); files.add(new File("C:\\name4\\ed")); files.add(new File("E:\\name3\\eddy")); files.add(new File("D:\\name2\\edd")); System.out.println("Default Sort"); Collections.sort(files); for(File file : files) System.out.println(file.getCanonicalPath()); System.out.println("Custom Sort"); Collections.sort(files,new CustomSort()); for(File file : files) System.out.println(file.getCanonicalPath()); } } class CustomSort implements Comparator<File>{ @Override public int compare(File o1, File o2){ String o1_parent = o1.getParentFile().getName(); String o2_parent = o2.getParentFile().getName(); int result = 0; if(o1_parent != null && o2_parent != null) result = o1_parent.compareTo(o2_parent); else result = o1.getName().compareTo(o2.getName()); return result; } } Result Default Sort C:\\name4\\ed D:\\name2\\edd E:\\name3\\eddy F:\\name1\\eddie Custom Sort F:\\name1\\eddie D:\\name2\\edd E:\\name3\\eddy C:\\name4\\edIn the example above, the first sort is done by natural ordering the second sort is done by our custom sort. In the first sort, the names
{ed, edd, eddy, eddie}
are compared. In the second sort, the parent names {name1, name2, name3, name4}
are compared.
If you're planning to create a sorting algorithm from scratch, you should read the compare() description in the documentation.
Comparator's Methods
Comparator has several methods that we can use. I'll demonstrate some of them here. If you wanna see all Comparator's method, go to the Comparator documentation. You need to be knowledgeable about generics and lambda expression to understand the syntax of the methods that I'm gonna explain in this chapter.
comparing() Method
This method accepts a function that extracts a Comparable sort key from a type T, and returns a Comparator<T> that compares by that sort key.
This method has two forms. In this topic, I'm gonna demonstrate this one:
comparing(Function<? super T,? extends U> keyExtractor)
The parameter here is a method reference with return type. The Comparable sort key will be extracted from the input and the output is a Comparator with sort key extracted from the input. Comparable sort key is a key that we can get from objects that implement Comparable. In this method, this key helps us sort an input from a method reference.
import java.util.Comparator; import java.util.Collections; import java.util.ArrayList; public class SampleClass{ public static void main(String[] args){ ArrayList<Data> data = new ArrayList<>(); System.out.println("Add elements..."); data.add(new Data("John","Wells",24)); data.add(new Data("Allen","Green",27)); data.add(new Data("Grace","Lessy",20)); Comparator<Data> comp = Comparator.comparing(Data::getLastName); System.out.println("Sort by last name..."); Collections.sort(data, comp); for(Data dat : data) System.out.println(dat.getName()); comp = Comparator.comparing(Data::getAge); Collections.sort(data, comp); System.out.println("Sort by age..."); for(Data dat : data) System.out.println(dat.getName() + " | " + dat.getAge()); } } class Data{ private String firstName; private String lastName; private Integer age; public Data(String firstName, String lastName, Integer age){ this.firstName = firstName; this.lastName = lastName; this.age = age; } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public Integer getAge(){ return age; } public String getName(){ return firstName + " " + lastName; } } Result Add elements... Sort by last name... Allen Green Grace Lessy John Wells Sort by age... Grace Lessy | 20 John Wells | 24 Allan Green | 27
nullsFirst() and nullsLast() Methods
nullsFirst()
returns a null-friendly comparator that considers null to be less than non-null. nullsLast()
returns a null-friendly comparator that considers null to be greater than non-null.Method Forms:
nullsFirst(Comparator<? super T> comparator)
nullsLast(Comparator<? super T> comparator)
This example demonstrates
nullsFirst()
and nullsLast()
.
import java.util.Comparator; import java.util.Collections; import java.util.ArrayList; public class SampleClass{ public static void main(String[] args){ ArrayList<String> names = new ArrayList<>(); System.out.println("Add elements..."); names.add("John Wells"); names.add("Allen Green"); names.add(null); names.add("Grace Lessy"); Comparator<String> comp = Comparator.nullsFirst(String::compareTo); System.out.println("Sort nulls first..."); Collections.sort(names, comp); for(String str : names) System.out.println(str); comp = Comparator.nullsLast(String::compareTo); System.out.println("Sort nulls last..."); Collections.sort(names, comp); for(String str : names) System.out.println(str); } } Result Add elements... Sort nulls first... null Allen Green Grace Lessy John Wells Sort nulls last... Allen Green Grace Lessy John Wells null
thenComparing() Methods
The first form:
thenComparing(Comparator<? super T> other)
Returns a lexicographic-order comparator with another comparator. If this(caller) Comparator considers two elements equal, i.e. compare(a, b) == 0, other(parameter) is used to determine the order. The returned comparator is serializable if the specified comparator is also serializable.
import java.util.Comparator; import java.util.Collections; import java.util.ArrayList; public class SampleClass{ public static void main(String[] args){ ArrayList<String> names = new ArrayList<>(); System.out.println("Add elements..."); names.add("John Wells"); names.add("allen Green"); names.add("Allen Green"); names.add(null); names.add("Grace Lessy"); Comparator<String> comp = Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER); Comparator<String> comp2 = comp.thenComparing(String::compareTo); System.out.println("Sort elements..."); Collections.sort(names,comp2); for(String str : names) System.out.println(str); } } Result Add elements... Sort elements... Allen Green allen Green Grace Lessy John Wells nullTake a look at the equal names. So first, we compare the names with String.CASE_INSENSITIVE_ORDER. Then, "Allen Green" and "allen Green" are equal when compared with insensitive order. Because two names are equal, the "other" comparator is used to compare these two equal names.
The "other" comparator copies that comparison pattern from compareTo() of String. compareTo() is case sensitive. Thus, "Allen Green" moved up and "allen Green" moved down because
"a"
's numerical representation is greater than "A"
's.
No comments:
Post a Comment