Collections用Comparable&&Comparator排序细节

在收集对象以后,对对象进行排序是经常使用的动做。不用亲自操做排序算法Java.util. Collections提供有sort()方法。因为必须有索引才能进行排序,所以 Collections的sort()方法接受List操做对象。例如:java

package coll_map;

import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List nums=Arrays.asList(3,6,2,7,5,9,0);
		Collections.sort(nums);
		System.out.println(nums);
	}
}

这里写图片描述 1.操做 Comparable算法

package coll_map;

import java.util.*;

class Sort2 {
	private String name;
	private String ID;
	private int balance;

	Sort2(String name, String ID, int balance) {
		this.name = name;
		this.balance = balance;
		this.ID = ID;
	}
	
	@Override
	public String toString() {
		return String.format("帐户(%s,%s,%d)", name,ID,balance);
	}
}
	public class Account{
		public static void main(String[] args) {
			List accounts=Arrays.asList(
					new Sort2("zhangsan","9958X",999),
					new Sort2("lisi","8779g",577),
					new Sort2("wanger","99098X",6988)
					);
			Collections.sort(accounts);
			System.out.println(accounts);
		}
	}

抛错: java.lang.ClassCastException 是由于Collections的sort方法,不知道是根据 Account的name、ID或 balance进行排序。sort()方法要求被排序的对象必须操做java.lang. Comparable接口,这个接口有个 compareto()方法必须返回大于0、等于0或小于0的数:数组

package coll_map;

import java.util.*;

class Sort2 implements Comparable<Sort2>{
	private String name;
	private String ID;
	private int balance;

	Sort2(String name, String ID, int balance) {
		this.name = name;
		this.balance = balance;
		this.ID = ID;
	}
	
	@Override
	public String toString() {
		return String.format("帐户(%s,%s,%d)", name,ID,balance);
	}

	@Override
	public int compareTo(Sort2 o) {
		// TODO 自动生成的方法存根
		return this.balance-o.balance;//判断排序条件
	}
}
	public class Account{
		public static void main(String[] args) {
			List accounts=Arrays.asList(
					new Sort2("zhangsan","9958X",999),
					new Sort2("lisi","8779g",577),
					new Sort2("wanger","99098X",6988)
					);
			Collections.sort(accounts);
			System.out.println(accounts);
		}
	}

这里写图片描述

collections的sot()方法在取得a对象与b对象进行比较时,会先将a对象扮演(Cast)为 comparable(也所以若对象没操做 Comparable,将会抛出 Classcastexception),而后调用 a.compareto(b),若是a对象顺序上小于b对象则返回小于0的值,若顺序上相等则返回0,若顺序上a大于b则返回大于0的值。所以,上面的范例,将会依余额从小到大排列帐户对象。前面的Sort类中,能够直接对 Integer进行排序,由于Integer就有操做 Comparable接口。 2.操做Comparator String有操做Comparable:ide

package coll_map;

import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List words=Arrays.asList("D","A","H","Y","E");
		Collections.sort(words);
		//若是只想用String的compareTo方法能够:words.sort(String::compareTo);
		System.out.println(words);
	}
}

这里写图片描述 可是若是有对象没法操做Comparable、拿不到原始码或者不能修改原始码。 好比让String排序结果反过来,就算修改String. Java后从新编译为 String.clas放回 rt jar中,也只有这个的JRE能够用,这已经不是标准API了。继承 string后再从新定义 compareto()也不可能,由于 String声明为 final,不能被继承。 Collections的sort()方法有另外一个重载版本,可接受 Java util. **Comparator接口的操做对象,若是使用这个版本,排序方式将根据 Comparator的 compare()定义来决定。**例如:this

package coll_map;
import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List<String> words=Arrays.asList("D","A","H","Y","E");
		Collections.sort(words,new StringSort());
		System.out.println(words);
	}
}
class StringSort implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		// TODO 自动生成的方法存根
		return -o1.compareTo(o2);
	}
}

Comparator的 compare()会传入两个对象,若是o1顺序上小于o2则返回小于0的值,顺序相等则返回0,顺序上o1大于o2则返回大于0的值。在这个范例中,因为 string自己就是 Comparable,因此将 compareto()返回的值乘上-1,就能够调换排列顺序。3d

package coll_map;

import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List<String> words=Arrays.asList("D","A","H","Y","E");
		//Collections.sort(words,(o1,o2) ->-o1.compareTo(o2));利用Lambda语法
		words.sort((o1,o2) ->-o1.compareTo(o2));//更简单利用Lambda语法
		System.out.println(words);
	}
}

在Java的规范中,与顺序有关的行为,一般要不对象自己是 Comparable,要不就是另行指定 Comparator对象告知如何排序。 例如,若是想针对数组进行排序,可使用java.util.Arrays的sort()方法,若是查询API文件,会发现该方法针对对象排序时有两个版本:一个版本是你收集在数组中的对象必须是 Comparable()不然会抛出Classcastexception ,另外一个版本则能够传入 compa rato指定排序方式.
Set的操做类之一java. util. TreeSet不只拥有收集不重复对象的能力,还可用红黑树方式排序收集的对象,条件就是收集的对象必须是 comparable(不然会抛出 Classcastexception)或者是在建立TreeSet时指定 Comparator 对象。 Queue的操做类之一 java util. Priorityqueue也是,收集至 Priorityqueue的对象,会根据你指定的优先权来决定对象在队列中的序,优先权的告知,要不就是对象必须是 comparable(不然会抛出Classcastexception)或者是建立Priorityqueue时指定Comparator对象。 若是有个List中某些索引处包括null,如今让null排在最前头,以后依字符串的长度由大到小排序,这样从新定义compare:code

@Override
	public int compare(String o1, String o2) {
		if(o1==o2) {
			return 0;
		}
		if(o1==null) {
			return -1;
		}
		if(o2==null) {
			return 1;
		}
		if(o1.length()==o2.length()) {
			return 0;
		}
		if(o1.length()>o2.length()) {
			return -1;
		}
		return 1;
	}

固然其实能够利用高级语义API:orm

package coll_map;
import java.util.*;
import static java.util.Comparator.*;

public class SortDemo {
	public static void main(String[] args) {
		List<String> words=Arrays.asList("D","A","H","Y","E");
		words.sort(nullsFirst(reverseOrder));//高级语义
		System.out.println(words);
	}
}

reverseOrder()返回的 Comparator会是 Comparable对象上定义顺序的反序, nullsFirst接受 Comparator,在其定义的顺序上加上让null排在最前面的规则。 能够看到 import static适当的运用,可让程序码表达出自己操做的意图相比如下程序代码来讲清楚许多:对象

words.sort(Comparator.nullsFirst(Comparator.reverseOrder));

Conparator上还有不少方法可使用,例如 comparing与 thenComparing等方法,要运用这些方法,得了解更多JDK8的 Lambda特性,例如位于java.util.function套件中的 Function等接口的意义blog

相关文章
相关标签/搜索