Collections
sort函数定义
Collections是⼀个⼯具类,sort是其中的静态⽅法,是⽤来对List类型进⾏排序的,它有两种参数形式:
public static <T extends Comparable<? super T>> void sort(List<T> list) { list.sort(null); } public static <T> void sort(List<T> list, Comparator<? super T> c) { list.sort(c); }
基本使用
第一种方法
⾸先使⽤基本类型(此处使⽤Integer)来演示第⼀个⽅法:
static List<Integer> intList = Arrays.asList(2, 3, 1); private static void sortBaseTypeByDefaultMode() { System.out.println("before sort:"); System.out.println(Arrays.toString(intList.toArray())); System.out.println("========================="); Collections.sort(intList); System.out.println("after sort:"); System.out.println(Arrays.toString(intList.toArray())); } public static void main(String[] args) { leetcode.sortBaseTypeByDefaultMode(); }
运行结果如下:
第一种方法
可以看到,默认的排序是正序,那么如何实现逆序呢,这就要使⽤第⼆种⽅式了,即通过实现Comparator接⼝的compare⽅法来完成⾃定义排序,代码如下:
static List<Integer> intList = Arrays.asList(2, 3, 1); private static void sortBaseTypeByIDefineMode() { System.out.println("before sort:"); System.out.println(Arrays.toString(intList.toArray())); System.out.println("========================="); Collections.sort(intList, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // 返回值为int类型,⼤于0表⽰正序,⼩于0表⽰逆序 return o2 - o1; } }); System.out.println("after sort:"); System.out.println(Arrays.toString(intList.toArray())); } public static void main(String[] args) { // leetcode.sortBaseTypeByDefaultMode(); leetcode.sortBaseTypeByIDefineMode(); }
可以看到,已经实现了逆序的排序了。
⾃定义类的排序
接下来看看⾃定义类的排序:
定义⼀个Emp类:
public class Emp { private int empno; private String ename; public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Emp(int empno, String ename) { super(); this.empno = empno; this.ename = ename; } @Override public String toString() { return "empno:\t" + empno + "\tename:\t" + ename; } }
⾸先使⽤同样的⽅式来使⽤Collections.sort⽅法:
定义泛型违Emp类型的List,使⽤sort⽅法的第⼆种形式:
static List<Emp> empList; static { Emp emp1 = new Emp(2, "Guan YunChang"); Emp emp2 = new Emp(3, "Zhang Fei"); Emp emp3 = new Emp(1, "Liu Bei"); empList = Arrays.asList(emp1, emp2, emp3); } private static void sortEmpByIDefineMode() { System.out.println("before sort:"); System.out.println(Arrays.toString(empList.toArray())); System.out.println("========================="); Collections.sort(empList, new Comparator<Emp>() { @Override public int compare(Emp o1, Emp o2) { /*按员⼯编号正序排序*/ return o1.getEmpno() - o2.getEmpno(); /*按员⼯编号逆序排序*/ //return o2.getEmpno()-o1.getEmpno(); /*按员⼯姓名正序排序*/ //return o1.getEname().compareTo(o2.getEname()); /*按员⼯姓名逆序排序*/ //return o2.getEname().compareTo(o1.getEname()); } }); System.out.println("after sort:"); System.out.println(Arrays.toString(empList.toArray())); } public static void main(String[] args) { // leetcode.sortBaseTypeByDefaultMode(); // leetcode.sortBaseTypeByIDefineMode(); leetcode.sortEmpByIDefineMode(); }
运行结果如下:
那么使用第一种方式能不能行呢,答案是可以的,但是不是直接的使用sort,例如下面是要报错的:
Collections.sort(empList);
我们需要这样做:⾸先让Emp类继承Comparable接⼝并重写compareTo⽅法(为了和上⾯的排序⽅式区别开,此次按照员⼯姓名逆序排列):
@Override public int compareTo(Emp emp) { /*按员⼯编号正序排序*/ //return this.getEmpno()-emp.getEmpno(); /*按员⼯编号逆序排序*/ //return emp.getEmpno()-this.getEmpno(); /*按员⼯姓名正序排序*/ //return this.getEname().compareTo(emp.getEname()); /*按员⼯姓名逆序排序*/ return emp.getEname().compareTo(this.getEname()); }
main函数中调用方法
private static void sortEmpByIDafaultMode() { System.out.println("before sort:"); System.out.println(Arrays.toString(empList.toArray())); System.out.println("========================="); Collections.sort(empList); System.out.println("after sort:"); System.out.println(Arrays.toString(empList.toArray())); } public static void main(String[] args) { // leetcode.sortBaseTypeByDefaultMode(); // leetcode.sortBaseTypeByIDefineMode(); // leetcode.sortEmpByIDefineMode(); leetcode.sortEmpByIDafaultMode(); }
运行结果如下:
总结:
1.对于String或Integer这些已经实现Comparable接⼝的类来说,可以直接使⽤Collections.sort⽅法传⼊list参数来实现默认⽅式(正序)排序;
2.如果不想使⽤默认⽅式(正序)排序,可以通过Collections.sort传⼊第⼆个参数类型为Comparator来⾃定义排序规则;
3.对于⾃定义类型(如本例⼦中的Emp),如果想使⽤Collections.sort的⽅式⼀进⾏排序,可以通过实现Comparable接⼝的compareTo⽅法来进⾏,如果不实现,则参考第2点;
4.jdk1.8的Comparator接⼝有很多新增⽅法,其中有个⽅法⽐较实⽤,是⽤来切换正序和逆序的:reversed(),代码如下:
private static void sortEmpByIDefineMode() { System.out.println("before sort:"); System.out.println(Arrays.toString(empList.toArray())); System.out.println("========================="); Comparator<Emp> comparator = new Comparator<Emp>() { @Override public int compare(Emp o1, Emp o2) { /*按员⼯编号正序排序*/ return o1.getEmpno() - o2.getEmpno(); /*按员⼯编号逆序排序*/ //return o2.getEmpno()-o1.getEmpno(); /*按员⼯姓名正序排序*/ //return o1.getEname().compareTo(o2.getEname()); /*按员⼯姓名逆序排序*/ //return o2.getEname().compareTo(o1.getEname()); } }; /* 新 的 逆 序 实 现 ⽅ 式 */ Collections.sort(empList, comparator.reversed()); System.out.println("after sort:"); System.out.println(Arrays.toString(empList.toArray())); }
复写的compare⽅法定义的是按员⼯编号正序排序,在使⽤reversed翻转后结果如下:
Comparator是个接⼝,可重写compare()及equals()这两个⽅法,⽤于⽐价功能;如果是null的话,就是使⽤元素的默认顺序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f,g这样,当然数字也是这样的。
compare(a,b)⽅法:根据第⼀个参数⼩于、等于或⼤于第⼆个参数分别返回负整数、零或正整数。
equals(obj)⽅法:仅当指定的对象也是⼀个 Comparator,并且强⾏实施与此 Comparator 相同的排序时才返回 true。
Collections.sort(list, new PriceComparator());的第⼆个参数返回⼀个int型的值,就相当于⼀个标志,告诉sort⽅法按什么顺序来对list进⾏排序。
具体实现代码⽅法如下:
package com.leetcode.www; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.TreeMap; /** * 书实体类 * * @author yjd */ public class Book implements Comparable { // 定义名为Book的类,默认继承⾃Object类 public int id;// 编号 public String name;// 名称 public double price; // 价格 private String author;// 作者 public GregorianCalendar calendar;// 出版⽇期 public Book() { this(0, "X", 0.0, new GregorianCalendar(), ""); } public Book(int id, String name, double price, GregorianCalendar calender, String author) { this.id = id; this.name = name; this.price = price; this.calendar = calender; this.author = author; } // 重写继承⾃⽗类Object的⽅法,满⾜Book类信息描述的要求 public String toString() { String showStr = id + "\t" + name; // 定义显⽰类信息的字符串 DecimalFormat formatPrice = new DecimalFormat("0.00");// 格式化价格到⼩数点后两位 showStr += "\t" + formatPrice.format(price);// 格式化价格 showStr += "\t" + author; SimpleDateFormat formatDate = new SimpleDateFormat("yyyy年MM⽉dd⽇"); showStr += "\t" + formatDate.format(calendar.getTime()); // 格式化时间 return showStr; // 返回类信息字符串 } public int compareTo(Object obj) { // Comparable接⼝中的⽅法 Book b = (Book) obj; return this.id - b.id; // 按书的id⽐较⼤⼩,⽤于默认排序 } public static void main(String[] args) { Book b1 = new Book(10000, "红楼梦", 150.86, new GregorianCalendar(2009, 01, 25), "曹雪芹、⾼鄂"); Book b2 = new Book(10001, "三国演义", 99.68, new GregorianCalendar(2008, 7, 8), "罗贯中 "); Book b3 = new Book(10002, "⽔浒传", 100.8, new GregorianCalendar(2009, 6, 28), "施耐庵 "); Book b4 = new Book(10003, "西游记", 120.8, new GregorianCalendar(2011, 6, 8), "吴承恩"); Book b5 = new Book(10004, "天龙⼋部", 10.4, new GregorianCalendar(2011, 9, 23), "搜狐"); TreeMap tm = new TreeMap(); tm.put(b1, new Integer(255)); tm.put(b2, new Integer(122)); tm.put(b3, new Integer(688)); tm.put(b4, new Integer(453)); tm.put(b5, new Integer(40)); Iterator it = tm.keySet().iterator(); Object key = null, value = null; Book bb = null; while (it.hasNext()) { key = it.next(); bb = (Book) key; value = tm.get(key); System.out.println(bb.toString() + "\t库存:" + tm.get(key)); } } }
⾃定义⽐较器和测试类:
package com.leetcode.www; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.List; public class UseComparator { public static void main(String args[]) { List<Book> list = new ArrayList<Book>(); // 数组序列 Book b1 = new Book(10000, "红楼梦", 150.86, new GregorianCalendar(2009, 01, 25), "曹雪芹、⾼鄂"); Book b2 = new Book(10001, "三国演义", 99.68, new GregorianCalendar(2008, 7, 8), "罗贯中 "); Book b3 = new Book(10002, "⽔浒传", 100.8, new GregorianCalendar(2009, 6, 28), "施耐庵 "); Book b4 = new Book(10003, "西游记", 120.8, new GregorianCalendar(2011, 6, 8), "吴承恩"); Book b5 = new Book(10004, "天龙⼋部", 10.4, new GregorianCalendar(2011, 9, 23), "搜狐"); list.add(b1); list.add(b2); list.add(b3); list.add(b4); list.add(b5); // Collections.sort(list); //没有默认⽐较器,不能排序 System.out.println(" 数 组 序 列 中 的 元 素 :"); myprint(list); Collections.sort(list, new PriceComparator()); // 根据价格排序 System.out.println("按书的价格排序:"); myprint(list); Collections.sort(list, new PriceComparator().reversed()); // 根据价格排序 System.out.println("按书的价格降序排序:"); myprint(list); Collections.sort(list, new CalendarComparator()); // 根据时间排序 System.out.println("按书的出版时间排序:"); myprint(list); } // ⾃定义⽅法:分⾏打印输出list中的元素 public static void myprint(List<Book> list) { Iterator it = list.iterator(); // 得到迭代器,⽤于遍历list中的所有元素 while (it.hasNext()) { // 如果迭代器中有元素,则返回true System.out.println("\t" + it.next());// 显⽰该元素 } } // ⾃定义⽐较器:按书的价格排序 static class PriceComparator implements Comparator { public int compare(Object object1, Object object2) {// 实现接⼝中的⽅法 Book p1 = (Book) object1; // 强制转换 Book p2 = (Book) object2; return new Double(p1.price).compareTo(new Double(p2.price)); } } // ⾃定义⽐较器:按书出版时间来排序 static class CalendarComparator implements Comparator { public int compare(Object object1, Object object2) {// 实现接⼝中的⽅法 Book p1 = (Book) object1; // 强制转换 Book p2 = (Book) object2; return p2.calendar.compareTo(p1.calendar); } } }