Collections.sort对List排序的两种方法

一、Collections.sort的简单使用

说到List的排序,第一反应当然是使用Collections.sort,方便简单。下面实现一下~~

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void sortStrings() {  
  2.     List<String> list = new ArrayList<String>();  
  3.     list.add("ccc");  
  4.     list.add("aaa");  
  5.     list.add("bbb");  
  6.     //排序  
  7.     Collections.sort(list);  
  8.     //输出  
  9.     Log.d(TAG, "-----------对字符串排序-----------");  
  10.     for(String item : list) {  
  11.         Log.d(TAG, item.toString());  
  12.     }  
  13. }  

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 02-03 10:32:25.821: D/wxx(4732): -----------对字符串排序-----------  
  2. 02-03 10:32:25.821: D/wxx(4732): aaa  
  3. 02-03 10:32:25.821: D/wxx(4732): bbb  
  4. 02-03 10:32:25.821: D/wxx(4732): ccc  


可见,实现了对List<String>的排序,非常简单。



二、问题提出

但在我们的项目中列表List的元素类型经常是自定义的,下面自定义了一个实体类Person:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Person {  
  2.   
  3.     private String name;  
  4.     private int age;  
  5.       
  6.     public Person(String name, int age) {  
  7.         this.name = name;  
  8.         this.age = age;  
  9.     }  
  10. }  

然后,想对Person的列表List<Person>进行排序,首先想到的也是通过Collections.sort进行排序:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void sortPerson() {  
  2.     Person p1 = new Person("ccc", 20);  
  3.     Person p2 = new Person("aaa", 18);  
  4.     Person p3 = new Person("bbb", 16);  
  5.       
  6.     List<Person> list = new ArrayList<Person>();  
  7.     list.add(p1);  
  8.     list.add(p2);  
  9.     list.add(p3);  
  10.       
  11.     //排序  
  12.     Collections.sort(list);  
  13. }  

发现,代码直接报错了:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable for the arguments (List<Person>). The inferred type Person is not a valid substitute for the bounded   
  2.  parameter <T extends Comparable<? super T>>  

从上面可知,Person不是一个有效的参数类型,而应该extends Comparable。为什么?

原来,要排序嘛当然要有排序的规则,比如按身高从高到低,按年龄从小到大,等等,也就是要有比较。而String这个对象已经帮我们实现了Comparable接口,所以String类型自己就是可以比较的。而我们的Person如果想要排序,也必须能够按某种规则进行比较,也就是要实现一个比较器。我们可以通过实现Comparable或Comparator接口实现比较器 。



三、Comparable实现排序

Comparable实现比较器,是定义在Person类的内部的,所以实体类Person需要implements Comparable<Person>,然后重写compareTo方法,在此方法里实现比较规则,规则就是先比较名字,如果名字不一样则返回比较结果,如果名字一样,再比较年龄,返回比较结果:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Person implements Comparable<Person> {  
  2.   
  3.     public String name;  
  4.     public int age;  
  5.       
  6.     public Person(String name, int age) {  
  7.         this.name = name;  
  8.         this.age = age;  
  9.     }  
  10.   
  11.     public int compareTo(Person another) {  
  12.         int i = name.compareTo(another.name); //比较名字字符串  
  13.         if (i == 0) { //如果名字一样,则继续比较年龄  
  14.             return age - another.age;  
  15.         } else { //首先比较名字,名字不一样,则返回比较结果  
  16.             return i;  
  17.         }  
  18.     }  
  19. }  
后面就是对List<Person>进行排序并输出:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void sortByComparable() {  
  2.     Person p1 = new Person("bbb", 20);  
  3.     Person p2 = new Person("aaa", 18);  
  4.     Person p3 = new Person("bbb", 16);  
  5.       
  6.     List<Person> list = new ArrayList<Person>();  
  7.     list.add(p1);  
  8.     list.add(p2);  
  9.     list.add(p3);  
  10.       
  11.     //排序  
  12.     Collections.sort(list);  
  13.     //输出  
  14.     Log.d(TAG, "-----------使用Comparable实现的排序-----------");  
  15.     for(Person item : list) {  
  16.         Log.d(TAG, "name = "+item.name+"age = "+item.age);  
  17.     }  
  18. }  

检查输出结果是否正确:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 02-03 12:05:31.356: D/wxx(9936): -----------使用Comparable实现的排序-----------  
  2. 02-03 12:05:31.356: D/wxx(9936): name = aaaage = 18  
  3. 02-03 12:05:31.356: D/wxx(9936): name = bbbage = 16  
  4. 02-03 12:05:31.356: D/wxx(9936): name = bbbage = 20  





四、Comparator实现排序

Comparator实现比较器,是定义在Person类的外部的,因此实体类Person不需要做任何变化,如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Person {  
  2.   
  3.     public String name;  
  4.     public int age;  
  5.       
  6.     public Person(String name, int age) {  
  7.         this.name = name;  
  8.         this.age = age;  
  9.     }  
  10. }  

我们的比较器My Comparator的实现,主要是覆盖compare方法,在这个方法内实现比较的规则,具体代码:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MyComparator implements Comparator<Person> {  
  2.   
  3.     public int compare(Person one, Person two) {  
  4.         int i = one.name.compareTo(two.name); //比较名字字符串  
  5.         if (i == 0) { //如果名字一样,则继续比较年龄  
  6.             return one.age - two.age;  
  7.         } else { //首先比较名字,名字不一样,则返回比较结果  
  8.             return i;  
  9.         }  
  10.     }  
  11.       
  12. }  

上面的排序规则是:先比较name值进行排序,如果name值一样 ,再比较age值排序。


最后,当然是用我们的比较器对List<Person>进行排序:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void sortByComparator() {  
  2.     Person p1 = new Person("bbb", 20);  
  3.     Person p2 = new Person("aaa", 18);  
  4.     Person p3 = new Person("bbb", 16);  
  5.       
  6.     List<Person> list = new ArrayList<Person>();  
  7.     list.add(p1);  
  8.     list.add(p2);  
  9.     list.add(p3);  
  10.       
  11.     //排序  
  12.     Collections.sort(list, new MyComparator());  
  13.     //输出  
  14.     Log.d(TAG, "-----------使用Comparator实现的排序-----------");  
  15.     for(Person item : list) {  
  16.         Log.d(TAG, "name = "+item.name+"age = "+item.age);  
  17.     }  
  18. }  

查看排序后的输出结果是否正确:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 02-03 11:51:34.996: D/wxx(1355): -----------使用Comparator实现的排序-----------  
  2. 02-03 11:51:34.996: D/wxx(1355): name = aaaage = 18  
  3. 02-03 11:51:35.001: D/wxx(1355): name = bbbage = 16  
  4. 02-03 11:51:35.001: D/wxx(1355): name = bbbage = 20  




五、Comparable 与Comparator区别

上面已经分别实现了Comparable 与Comparator对List进行排序,他们有相似的地方,也有不同的地方:

1)Comparable 与Comparator都是java的接口,用来对自定义的实体对象进行比较;

2)Comparable 是定义在实体类内部的,所以实体类对象本身就有比较大小的可能。但如果想换一种比较规则,如先按年龄后按名字排序,那么就必须修改实体类Person本身;

3)Comparator是在实体类外部实现比较器的,所以对List排序时必须同时传入数据和比较器,如Collections.sort(list, new MyComparator());如果想换一种比较规则,则仅需要修改比较器MyComparator,而实体类Person则不需要改变;所以建议使用这种方法;

4)Comparable实现代码相对简单,Comparator实现代码相对复杂一点,但还是建议使用Comparator方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值