java list排序 是否是稳定排序_[改善Java代码]非稳定排序推荐使用List

我们知道Set与List的最大区别就是Set中的元素不可以重复(这个重复指的equals方法的返回值相等),其他方面则没有太大的区别了,在Set的实现类中有一个比较常用的类需要了解一下:TreeSet,该类实现了类默认排序为升序的Set集合,如果插入一个元素,默认会按照升序排列(当然是根据Comparable接口的compareTo的返回值确定排序位置了),不过,这样的排序是不是在元素经常变化的场景中也适用呢?我们来看例子:

1 importjava.util.SortedSet;2 importjava.util.TreeSet;3

4 public classClient {5 public static voidmain(String[] args) {6 SortedSet set = new TreeSet();7 //身高180CM

8 set.add(new Person(180));9 //身高175CM

10 set.add(new Person(175));11

12 for(Person p:set){13 System.out.println("身高:"+p.getHeight());14 }15 }16

17 static class Person implements Comparable{18 //身高

19 private intheight;20

21 public Person(int_age){22 height =_age;23 }24

25

26 public intgetHeight() {27 returnheight;28 }29

30

31 public void setHeight(intheight) {32 this.height =height;33 }34

35 //按照身高排序

36 public intcompareTo(Person o) {37 return height -o.height;38 }39

40 }41 }

程序输出:

身高:175身高:180

这没有问题,随着时间的推移,身高175cm的人长高了10cm,而180cm却保持不变,那排序的位置应该改变一下吧,看代码(只需修改main方法):

1 public static voidmain(String[] args) {2 SortedSet set = new TreeSet();3 //身高180CM

4 set.add(new Person(180));5 //身高175CM

6 set.add(new Person(175));7 //身高最矮的人大变身

8 set.first().setHeight(185);9 for(Person p : set) {10 System.out.println("身高:" +p.getHeight());11 }12 }

程序输出:

身高:185身高:180

很可惜,竟然没有重新排序,偏离了我们的预期。这正是下面要说明的问题,SortedSet接口(TreeSet实现了该接口)只是定义了在给集合加入元素时将其进行排序,并不能保证元素修改后的排序结果,因此TreeSet使用于不变量的集合数据排序,比如String、Integer等类型,但不适用于可变量的排序,特别是不确定何时元素会发生变化的数据集合。

原因知道了,那如何解决此类重排序问题呢?有两种方式:

(1).Set集合重排序

重新生成一个Set对象,也就是对原有的Set对象重排序,代码如下:

1 importjava.util.ArrayList;2 importjava.util.SortedSet;3 importjava.util.TreeSet;4

5 public classClient {6 public static voidmain(String[] args) {7 SortedSet set = new TreeSet();8 //身高180CM

9 set.add(new Person(180));10 //身高175CM

11 set.add(new Person(175));12 //身高最矮的人大变身

13 set.first().setHeight(185);14 //set重排序

15 set = new TreeSet(new ArrayList(set));

//set = new TreeSet(set);该构造函数只是原Set的浅拷贝,如果里面有相同的元素,是不会重新排序的16 for(Person p : set) {17 System.out.println("身高:" +p.getHeight());18 }19 }20

21 static class Person implements Comparable{22 //身高

23 private intheight;24

25 public Person(int_age) {26 height =_age;27 }28

29 public intgetHeight() {30 returnheight;31 }32

33 public void setHeight(intheight) {34 this.height =height;35 }36

37 //按照身高排序

38 public intcompareTo(Person o) {39 return height -o.height;40 }41

42 }43 }

程序输出:

身高:180身高:185

就一句话即可重新排序。可能有读者会问,使用TreeSet(SortedSet< E > s)这个构造函数不是可以更好地解决问题吗?不行,该构造函数只是原Set的浅拷贝,如果里面有相同的元素,是不会重新排序的。

(2).彻底重构掉TreeSet,使用List解决问题

我们之所以使用TreeSet是希望实现自动排序,即使修改也能自动排序,既然它无法实现,那就用List来代替,然后再使用Collections.sort()方法对List排序.看代码:

1 importjava.util.ArrayList;2 importjava.util.Collections;3 importjava.util.List;4 importjava.util.TreeSet;5

6 public classClient {7 public static voidmain(String[] args) {8 List list = new ArrayList();9 //身高180CM

10 list.add(new Person(180));11 //身高175CM

12 list.add(new Person(175));13 //身高最矮的人大变身

14 list.get(1).setHeight(185);15

16 //排序

17 Collections.sort(list);18 for(Person p : list) {19 System.out.println("身高:" +p.getHeight());20 }21 }22

23 static class Person implements Comparable{24 //身高

25 private intheight;26

27 public Person(int_age) {28 height =_age;29 }30

31 public intgetHeight() {32 returnheight;33 }34

35 public void setHeight(intheight) {36 this.height =height;37 }38

39 //按照身高排序

40 public intcompareTo(Person o) {41 return height -o.height;42 }43

44 }45 }

程序输出:

身高:180身高:185

两种方法都可以解决我们的困境,到底哪一个是最优的呢?对于不变量的排序,例如直接量(也就是8个基本类型)、String类型等,推荐使用TreeSet,而对于可变量,例如我们自己写的类,可能会在逻辑处理中改变其排序关键值的,则建议使用List自行排序。

又有问题了,如果需要保证集合中元素的唯一性,又要保证元素值修改后排序正确,那该如何处理呢?List不能保证集合中的元素唯一,它是可以重复的,而Set能保证元素唯一,不重复。如果采用List解决排序问题,就需要自行解决元素重复问题(若要剔除也很简单,转变为HashSet,剔除后再转回来)。若采用TreeSet,则需要解决元素修改后的排序问题,孰是孰非,就需要根据具体的开发场景来决定了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值