排序的算法是我们最常用的算法,初学程序,每个人都尝试过排序。但只是局限于简单的排序。
如将下列数字进行排序
1,3,5,8,3,6
于是我们得出结果
1,3,3,5,6,8
将下列字母(字符)进行排序
a,i,e,f,w,s
于是我们得出结果
a,e,f,i,s,w
但是我们遇到的情况就不是如此简单了。如给公司里的商品进行排序,我们很轻易的想到按照商品的名称排序不
就完了,而且简单明了。但现实并如我们相信般简单。同一商品名称可以有不同的批次,进货时间,可能还会有单价
的不同。显然只根据商品名称排序是不合理的。
Java的比较器有两类,分别是Comparable接口和Comparator接口。在为对象数组进行排序时,比较器的作用非
常明显。
一Comparable接口——可比较接口
Comparable实现该接口的提示:这个类的实例可以比较大小,可以进行自然排序,定义了默认的比较规则。
Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo()
方法被称为它的自然比较方法。
实现此接口的对象可以通过Collections.sort()和Arrays.sort()进行自动排序,也可以用作有序映射中的键或有序集合
中的元素,无需指定比较器。
compareTo()方法返回正数表示大,负数表示小,0表示相等。
comparable接口定义的方法:
接口声明:
<span style="font-size:18px;">public interface Comparable<T>{ int compareTo(T o); }</span>
二Comparator接口——比较器接口
Comparator接口用于定义临时比较规则,而不是默认比较规则。可以将Comparator传递给sort()方法,从而允许
在排序顺序上实现精确控制。还可为那些没有自然顺序的对象collection提供排序。
Comparator接口比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或
正整数。
Comparator接口的方法:
接口声明:
<span style="font-size:18px;">public interface Comparator<T>{ int compare(T o1, T o2); }</span>
三示例
所有可以排序的类都实现了java.lang.Comparable接口,Comparable接口与中只有一个方法compareTo(Object
obj),该方法:返回0表示this=obj;返回整数表示this>obj;返回负数表示this<obj。实现了Comparable接口的类通过
实现compareTo()方法从而确定该类对象的排序方式。
(1)使用Comparable接口
让需要进行排序的类实现Comparable接口,重写其中的compareTo(T o)方法,在其中定义排序规则,那么就可以
直接调用Collections.sort()来排序对象集合,实例如下:
<span style="font-size:18px;">import java.util.*; public class Test{ public static void main(String[] args){ List l1 = new ArrayList(); l1.add(new Name("Karl","M")); l1.add(new Name("Steven","Lee")); l1.add(new Name("John","O")); l1.add(new Name("Tom","M")); //排序前遍历 for(Object o:l1){ System.out.println(o); } //排序 Collections.sort(l1); System.out.println("---------------"); //排序后遍历 for(Object o:l1){ System.out.println(o); } } } class Name implements Comparable{ private String firstName; private String lastName; public Name(String firstName,String lastName){ this.firstName = firstName; this.lastName = lastName; } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public String toString(){ return firstName + " " +lastName; } public boolean equals(Object obj){ if(obj instanceof Name){ Name name = (Name)obj; return (firstName.equals(name.firstName))&&(lastName.equals(name.lastName)); }else{ return super.equals(obj); } } public int hashCode(){ return firstName.hashCode(); } public int compareTo(Object o){ Name n = (Name)o; int lastCmp = lastName.compareTo(n.lastName); return (lastCmp!=0?lastCmp:firstName.compareTo(n.firstName)); } }</span>
运行结果:
(2)使用Comparator接口
如果对java比较熟悉的会知道java.util.Comparator接口。要实现里面的函数 int compare(Object o1, Object o2)返
回一个基本类型的整型,返回负数表示o1 小于o2,返回0 表示o1和o2相等,返回正数表示o1大于o2。
再举个简单例子然后用程序实现。如公司要将员工进行排序(不要说领导排在前面),假设我们的需求比较复杂。先
进行姓排序,谁的姓拼音靠前,谁就排前面。然后对名字进行排序。恩.如果同名,女性排前头。如果名字和性别都相
同,年龄小的排前头。ok,一个也不算复杂的需求。
网上案例经过改写的实例:
于是我们设计的人员类要有几个变量,firstname,lastname,sex,age分别表示姓,名,性别,年龄。 Person.java
源文件代码:
<span style="font-size:18px;">public class Person { String firstname,lastname; Boolean sex; Integer age; public Person(String firstname,String lastname,Boolean sex,Integer age) { this.firstname = firstname; this.lastname = lastname; this.sex = sex; this.age = age; } public String getFirstName(){ return firstname; } public String getLastName(){ return lastname; } public Boolean getSex(){ return sex; } public Integer getAge(){ return age; } //为了输入方便,重写了toString() public String toString(){ return firstname +" "+lastname+" "+(sex.booleanValue()?"男":"女")+" "+age; } } </span>
下面是要实现比较器,Comparators.java源文件代码:
<span style="font-size:18px;">import java.util.*; public class Comparators{ public static java.util.Comparator getComparator(){ return new java.util.Comparator(){ public int compare(Object o1, Object o2){ if(o1 instanceof String){ return compare((String)o1,(String)o2); }else if (o1 instanceof Integer) { return compare( (Integer) o1, (Integer) o2); }else if (o1 instanceof Person) { return compare( (Person) o1, (Person) o2); }else { System.err.println("未找到合适的比较器"); return 1; } } public int compare(String o1, String o2){ String s1 = (String) o1; String s2 = (String) o2; int len1 = s1.length(); int len2 = s2.length(); int n = Math.min(len1, len2); char v1[] = s1.toCharArray(); char v2[] = s2.toCharArray(); int pos = 0; while(n-- != 0){ char c1 = v1[pos]; char c2 = v2[pos]; if(c1 != c2){ return c1 - c2; } pos++; } return len1 - len2; } public int compare(Integer o1, Integer o2){ int val1 = o1.intValue(); int val2 = o2.intValue(); return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1)); } public int compare(Boolean o1, Boolean o2){ return (o1.equals(o2)? 0 : (o1.booleanValue()==true?1:-1)); } public int compare(Person o1, Person o2){ String firstname1 = o1.getFirstName(); String firstname2 = o2.getFirstName(); String lastname1 = o1.getLastName(); String lastname2 = o2.getLastName(); Boolean sex1 = o1.getSex(); Boolean sex2 = o2.getSex(); Integer age1 = o1.getAge(); Integer age2 = o2.getAge(); return (compare(firstname1, firstname2) == 0 ? (compare(lastname1, lastname2) == 0 ? (compare(sex1, sex2) == 0 ? (compare(age1, age2) == 0 ? 0 : compare(age1, age2)) : compare(sex1, sex2)) : compare(lastname1, lastname2)) : compare(firstname1, firstname2)); } }; } } </span>
测试:
<span style="font-size:18px;">import java.util.*; public class Test{ public static void main(String[] args){ List l1 = new ArrayList(); l1.add(new Person("ouyang", "feng", Boolean.TRUE, new Integer(27))); l1.add(new Person("zhuang", "gw", Boolean.TRUE, new Integer(27))); l1.add(new Person("zhuang", "gw", Boolean.FALSE, new Integer(27))); l1.add(new Person("zhuang", "gw", Boolean.FALSE, new Integer(2))); for(Object o:l1){ System.out.println(o); } Collections.sort(l1, Comparators.getComparator()); System.out.println("---------------"); for(Object o:l1){ System.out.println(o); } } } </span>
运行结果: