博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[改善Java代码]非稳定排序推荐使用List
阅读量:6444 次
发布时间:2019-06-23

本文共 4941 字,大约阅读时间需要 16 分钟。

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

1 import java.util.SortedSet; 2 import java.util.TreeSet; 3  4 public class Client { 5     public static void main(String[] args) { 6         SortedSet
set = new TreeSet
(); 7 //身高180CM 8 set.add(new Person(180)); 9 //身高175CM10 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 int height;20 21 public Person(int _age){22 height = _age;23 }24 25 26 public int getHeight() {27 return height;28 }29 30 31 public void setHeight(int height) {32 this.height = height;33 }34 35 //按照身高排序36 public int compareTo(Person o) {37 return height - o.height;38 }39 40 }41 }

 

程序输出:

身高:175身高:180

 

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

1     public static void main(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 import java.util.ArrayList; 2 import java.util.SortedSet; 3 import java.util.TreeSet; 4  5 public class Client { 6     public static void main(String[] args) { 7         SortedSet
set = new TreeSet
(); 8 // 身高180CM 9 set.add(new Person(180));10 // 身高175CM11 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 int height;24 25 public Person(int _age) {26 height = _age;27 }28 29 public int getHeight() {30 return height;31 }32 33 public void setHeight(int height) {34 this.height = height;35 }36 37 // 按照身高排序38 public int compareTo(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 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 import java.util.TreeSet; 5  6 public class Client { 7     public static void main(String[] args) { 8         List
list = new ArrayList
(); 9 // 身高180CM10 list.add(new Person(180));11 // 身高175CM12 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 int height;26 27 public Person(int _age) {28 height = _age;29 }30 31 public int getHeight() {32 return height;33 }34 35 public void setHeight(int height) {36 this.height = height;37 }38 39 // 按照身高排序40 public int compareTo(Person o) {41 return height - o.height;42 }43 44 }45 }

 

程序输出:

身高:180身高:185

 

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

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

 

转载于:https://www.cnblogs.com/DreamDrive/p/5660201.html

你可能感兴趣的文章
CentOS6.4 安装VirtualBox
查看>>
从30岁到35岁:为你的生命多积累一些厚度
查看>>
Java中集合与数组之间的转化
查看>>
JQUERY 获取span标签id中包含-btnInnerEl的所有项
查看>>
servlet初步认识
查看>>
linux服务器 磁盘和文件系统管理(二) LVM逻辑卷管理的基本操作
查看>>
软raid之详解
查看>>
优先级队列
查看>>
centos6.9安装confluence 6.5.0
查看>>
Python 中的 10 个常见安全漏洞,以及如何避免(上)
查看>>
11.互传文件、用户配置文件和密码配置文件、用户组及用户管理
查看>>
Dubbo源码解析 — 服务引用原理
查看>>
盘点2019年PHP高级开发工程师面试题及答案汇总
查看>>
jenkins自动部署更新AWS ECS服务
查看>>
vscode波浪线去除
查看>>
phalapi-入门篇2(把它玩起来)
查看>>
如何学习技术?(转)
查看>>
OSChina 周日乱弹 ——姐姐妹妹都没有的 我也不想要
查看>>
akka学习
查看>>
权重随机 (choice和sample)
查看>>