A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王鹏伟 中级黑马   /  2013-2-26 14:11  /  3707 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

TreeSet两种排序方法:对象具有比较功能实现Comparable接口,另一种是定义比较器,这两方法有区别吗?什么时候用这两种方法,看视频中在对象中有比较功能进行年龄排序,又想按照姓名排序,又定义了一个比较器放到new集合中,这里在对象中改改CompareTo方法不就可以吗,为什么还要再创建个比较器?还有两种同时存在时是按照比较器进行排序的?




评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

5 个回复

倒序浏览
因为在实际开发中一般不能改源代码,改源代码可能会引起许多其他问题。当自定义类具有比较性,同时又传入比较器时会采用比较器的比较方法,
比较器可以随时定义,又不用改源代码,当自定义类具有的排序方式不是所需要的排序方式时,可以自定义比较器进行排序。

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
这个看爱好吧 像我 实现接口放在类里面嫌太乱 就用比较器了
回复 使用道具 举报
下面是个人理解
首先明确一点对象能存进TreeSet的条件:要么对象自身具有可比较性,要么让TreeSet具有比较方法,或两者都有。
1、通过实现Compareable可让其自身具备可比较性,
而复写CompareTo方法可让该类具有自己特有的比较方式.
2,也可以通过定义比较器,再把比较器传给TreeSet,这样TreeSet就具有比较方式了

当我们定义一个Person类当初的需求是按年龄排序,但后业的需求又变为按姓名排序
这时我们会优先考虑用Comparator比较器实现,因为这样不用改动原有类的代码。
改成原代码的坏处是比较明显的
假如我们很久以前写了一个类,而且这个类已经用在很多地方,当我们改动这个类的代码时,那么很多地方的代码都要作出相应的改动,工作量和难度是可想而知的

当两种比较方式都存在时,肯定是用比较器的方法去比较,因为我觉得这样才符合常理

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系,然后将集合元素按升序排列,这种方式就是自然排序。(比较的前提:两个对象的类型相同)。
TreeSet的自然排序是根据集合元素的大小,TreeSet将他们以升序排列。如果需要实现定制排序,例如降序,则可以使用Comparator接口。该接口里包含一个int compare(T o1, T o2)方法,该方法用于比较o1和o2的大小。
   如果需要实现定制排序,则需要在创建TreeSet集合对象时,并提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
实现Comparable的称之为自然排序,你可以这样理解,一个类你实现了Comparable,那么这个类就有了自己本身的排序方式,比如你可以设置人以年龄为排序条件。
实现comparator的称之为定制排序,就是说你往集合里面加入人对象,如果他实现了comparable接口,那么就以年龄排序了,但是如果你有特殊要求,比方说以身高为排序条件,那么你不想破坏原有的自然排序规则,就可以自己实现一个类实现comparator接口,自己定制实现以身高为排序规则,将这个实现类传入到set或者map的构造函数中去,
那么set和map就将你定义的这个排序规则作为排序条件了,也就是说当两Comparable与Comparator都存在时,以Comparator比较器为主
我觉得这么说应该很容易理解了。。。
归根结底一句话,当元素自身不具备比较性,或者具备的比较性不是所需要的。可以向集合构造函数中传入一个比较器,该比较器实现了Comparator接口并重写了compare(T o1,To2)方法来进行添加元素时的比较,这是毕老师上课时说的。

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马