前言
包装类Collections的排序方法可以运用到各种集合框架,非常方便
接口分析
Comparable接口
- Comparable接口在 java.lang.Comparable 包下
- Comparable接口的实现方法:public int compareTo(T t);
- Comparable接口是在集合的(类的)内部实现的排序方式,调用的实质 t1.compareTo(t2);
- 在排序对象本身支持相互比较所需要的接口(如Integer、String、Double、Float等)时,可以直接调用 Collections.sort() 方法的Comparable接口(参考程序示例)
- 当数值或ASCII码值从小到大的默认顺序或者排序的根据对象不满足程序需求时,可以重写compareTo方法(参考程序示例)
Comparator接口
- Comparator接口在 java.util.Comparator 包下
- Comparator接口的实现方法:public int compare(T t1, T t2);
- Comparator接口是在集合的(类的)外部实现的排序方式,需要用到一个比较容器,*调用的实质是 compare(t1 , t2);*(参考程序示例)
- 在排序对象本身不支持相互比较所需要的接口,例如对整数采用绝对值大小排序,显然对象本身的Integer自然排序是不能实现的,同时如果Integer类也不容许你在它的内部重写compareTo()去改变它的排序行为,所以就可以用到Comparator接口(参考程序示例)
compareTo和compare方法
Comparable接口的实现方法:public int compareTo(T t),调用的实质 t1.compareTo(t2);
在方法内部返回一个运算结果,例如返回:t1.x - t2.x,则按从小到大的顺序排序
若返回:t2.x - t1.x,则按从大到小的顺序排序
Comparator接口的实现方法:public int compare(T t1, T t2),调用的实质是 compare(t1 , t2);
在方法内部返回一个运算结果,例如返回:t1.x - t2.x,则按从小到大的顺序排序
若返回:t2.x - t1.x,则按从大到小的顺序排序
compareTo默认的调用可以实现字符串的比较,比较方法:先比较第一个字符,不同则返回ASCII码的差值,若第一个字符相同,则比较第二个字符,若前面字符相同则比较长度。
例如:
String a = 'abc'; String b = 'cde'; String c = 'abcde'; int d = a.compareTo(b); int e = a.compareTo(c);
|
返回d = -2,由a的ASCII码值减去b的ASCII码值得来。e = -2,因为前字符相同,a.length() - c.length() = -2
相关之处
- 对于一个对象的排序,既可以用Comparable接口实现,也能用Comparator接口实现,只是两种排序的实现方式不同,
- 在某些情况的排序下,可以用Comparator接口,在接口的compare方法中再次调用compareTo方法进行比较。例如如下情况:
输入学生的学号、姓名、班级、成绩,分别根据这四个数据进行排序。
对学号的排序,可以调用Comparable接口重写comparaTo方法按学号从小到大排序
对姓名的排序,可以实现一个比较容器,在容器中重写compare方法,在compare方法中调用compareTo方法实现对字符串的比较,然后返回对字符串的比较结果。
class NameUPComparator implements java.util.Comparator { public int compare(Object o1, Object o2) { Student s1 = (Student)o1; Student s2 = (Student)o2; return s1.getName().compareTo(s2.getName()); } }
|
在调用sort方法时,则要通过:
Collections.sort(studentList,new NameUPComparator());
|
程序示例
调用默认的Comparable接口
import java.util.ArrayList;
import java.util.Collections;
public class CompObj {
public String toString() { return "[x = " + x + "]"; }
public static void main(String[] args) { ArrayList<Integer> al = new ArrayList<Integer>(); al.add(3); al.add(1); al.add(2); System.out.println("Before sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } Collections.sort(al); System.out.println("After sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } }
|
运行结果如下所示:
调用重写compareTo方法的Comparable接口
根据x值排序
import java.util.ArrayList; import java.util.Collections;
public class CompObj implements java.lang.Comparable {
int x; int y;
public CompObj(int n1, int n2) { x = n1; y = n2; }
public String toString() { return "[x = " + x + ", y = " + y + "]"; }
public int compareTo(Object o) { CompObj co = (CompObj) o; if (this.x != co.x) { return this.x - co.x; } else { return this.y - co.y; } }
public static void main(String[] args) { ArrayList<CompObj> al = new ArrayList<CompObj>(); al.add(new CompObj(3, 1)); al.add(new CompObj(1, 3)); al.add(new CompObj(2, 2)); al.add(new CompObj(2, 1)); System.out.println("Before sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } Collections.sort(al); System.out.println("After sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } }
}
|
输出结果:
注意事项
调用重写compareTo方法的Comparator接口
根据y值排序
import java.util.ArrayList; import java.util.Collections;
class ObjComparator implements java.util.Comparator { public int compare(Object o1, Object o2) { CompObj co1 = (CompObj) o1; CompObj co2 = (CompObj) o2; if (co1.y != co2.y) { return co1.y - co2.y; } else { return co1.x - co2.x; } } }
public class CompObj { int x; int y;
public CompObj(int n1, int n2) { x = n1; y = n2; }
public String toString() { return "[x = " + x + ", y = " + y + "]"; }
public static void main(String[] args) { ArrayList al = new ArrayList(); al.add(new CompObj(3, 2)); al.add(new CompObj(1, 3)); al.add(new CompObj(1, 2)); System.out.println("Before sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } Collections.sort(al, new ObjComparator()); System.out.println("After sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } } }
|
调用重写compareTo方法的Comparator接口实现绝对值排序
根据x的绝对值排序
import java.util.ArrayList; import java.util.Collections;
class AbsComparator implements java.util.Comparator { public int compare(Object o1, Object o2) { CompObj co1 = (CompObj) o1; CompObj co2 = (CompObj) o2; int v1 = Math.abs(co1.x); int v2 = Math.abs(co2.x); return v1 - v2; } }
public class CompObj { int x; int y;
public CompObj(int n1, int n2) { x = n1; y = n2; }
public String toString() { return "[x = " + x + ", y = " + y + "]"; }
public static void main(String[] args) { ArrayList al = new ArrayList(); al.add(new CompObj(3, 2)); al.add(new CompObj(-2, 3)); al.add(new CompObj(1, 2)); System.out.println("Before sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } Collections.sort(al, new AbsComparator()); System.out.println("After sort!"); for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i)); } } }
|