1. Comparable interface
The sort method in the Arrays class can sort the object array, but the class to which the object belongs must implement the Comparable interface.
The following is an example, the
object array is sorted by score
package com.fu.demo;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,50);
a[1]=new A(2,90);
a[2]=new A(4,80);
a[3]=new A(3,70);
Arrays.sort(a);
for (A aa:a) {
System.out.println(aa);
}
}
}
class A implements Comparable<A>{
private int num;
private double score;
public A(int num, double score) {
this.num = num;
this.score = score;
}
@Override
public int compareTo(A o) {
return Double.compare(score,o.score);
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
'}';
}
}
2. Comparator interface
In the following example, sort sorts the String array lexicographically. This is because String implements the Comparable interface. If our requirements change at this time, what should we do if we need to sort String by length? Here we can introduce the Comparator interface.
import java.util.Arrays;
import java.util.Date;
public class Test {
public static void main(String[] args) {
String[] arr={
"bbb","aa","c","dddd"};
for (String str:arr) {
System.out.println(str);
}
Arrays.sort(arr);
for (String str:arr) {
System.out.println(str);
}
}
}
The second parameter of the overloaded method of sort is to pass a comparator, which is an instance of a class that implements the Comparator interface. Let's look at an example, sorting by string length.
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test2 {
public static void main(String[] args) {
String[] array={
"bbb","aa","c","dddd"};
for (String str:array) {
System.out.println(str);
}
Arrays.sort(array,new LengthComparator());
for (String str:array) {
System.out.println(str);
}
}
}
//这个类的实例就是比较器
class LengthComparator implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
}
In addition, the Comparator interface has many static methods. These static methods are very convenient to create comparators.
The static comparing method takes a "key extractor" function, which maps the type T to a comparable type. Apply this function to the objects to be compared, and then complete the comparison of the returned keys.
The following static method is used to sort by score
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,50);
a[1]=new A(2,90);
a[2]=new A(4,80);
a[3]=new A(3,70);
for (A aa:a) {
System.out.println(aa);
}
Arrays.sort(a,Comparator.comparing(A::getNum));//按num排序
for (A aa:a) {
System.out.println(aa);
}
}
}
class A{
private int num;
private double score;
public A() {
}
public A(int num, double score) {
this.num = num;
this.score = score;
}
public int getNum() {
return num;
}
public double getScore() {
return score;
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
'}';
}
}
This is of course much easier than implementing a Comparator manually. And the code is clearer.
We can also serialize the comparator with the thenComparing method to handle the situation where the comparison result is the same. E.g:
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,50);
a[1]=new A(3,90);
a[2]=new A(4,80);
a[3]=new A(3,70);
for (A aa:a) {
System.out.println(aa);
}
Arrays.sort(a,Comparator.comparing(A::getNum).thenComparing(A::getScore));
//先按num排序,再按score
for (A aa:a) {
System.out.println(aa);
}
}
}
class A{
private int num;
private double score;
public A() {
}
public A(int num, double score) {
this.num = num;
this.score = score;
}
public int getNum() {
return num;
}
public double getScore() {
return score;
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
'}';
}
}
There are many variations of these methods. You can specify a comparator for the keys extracted by the comparing and thencomparing methods. For example, according to sort by length first, and then sort by dictionary order.
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test2 {
public static void main(String[] args) {
String[] array={
"bb","aa","c","dddd"};
for (String str:array) {
System.out.println(str);
}
Arrays.sort(array,Comparator.comparing(String::length).thenComparing(String::compareTo));
for (String str:array) {
System.out.println(str);
}
}
}
Sort by name length first, then sort by score
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,100,"aa");
a[1]=new A(3,90,"bb");
a[2]=new A(4,80,"ddddddddd");
a[3]=new A(3,70,"cccc");
for (A aa:a) {
System.out.println(aa);
}
Arrays.sort(a,Comparator.comparing(A::getName,(s,t)->s.length()-t.length()).thenComparing(A::getScore));
//先按名字长度排序,再按score排序
for (A aa:a) {
System.out.println(aa);
}
}
}
class A{
private int num;
private double score;
private String name;
public A() {
}
public A(int num, double score, String name) {
this.num = num;
this.score = score;
this.name = name;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
public double getScore() {
return score;
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
", name='" + name + '\'' +
'}';
}
}
There are other static methods, Comparator.comparingInt, nullsFirst, etc., you can query the api and then call it.