黑马程序员技术交流社区

标题: 如何区分并使用集合中的两种比较的用法? [打印本页]

作者: 陈延真    时间: 2013-5-26 22:13
标题: 如何区分并使用集合中的两种比较的用法?
本帖最后由 陈延真 于 2013-5-30 21:28 编辑

Comparable:自然排序比较,被元素本身实现。
Comparator:比较器接口,用于集合实现。
这些是怎么个意思啊。。。?

作者: lpflpy    时间: 2013-5-26 22:50
当元素自身不具备比较性,或者具备的比较性不是所需要的。
这时需要让容器自身具备比较性。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

当两种排序都存在时,以比较器为主。定义一个类,实现Comparator接口,覆盖compare方法。

作者: 谢孔营    时间: 2013-5-26 22:59
Comparable:自然排序比较,被元素本身实现。
Comparator:比较器接口,用于集合实现
用程序解释更加清晰,有时候这两种可以转换,但是有时候不能转换,比较器可以根据自己的需要自定义比较条件
TreeSet内部数据结构是二叉树结构
comparable解释
class Person implements Comparable{//元素自身的排序
        private String name;
        private int age;
        public Person(String name, int age) {
                super();
                this.name = name;
                this.age = age;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
        @Override
        public String toString() {
                return "Person [name=" + name + ", age=" + age + "]";
        }
        @Override
        public int compareTo(Object o) {//覆盖接口的compareTo()方法,来定义元素自身排序的条件
                Person person = (Person) o;
                int temp = this.age - person.age ;
                return temp==0?this.name.compareTo(person.name):temp;//如果当前对象的值比另一个对象值大返回正。小返回负数,0相等               
        }
此种排序,是元素自身实现的,不用单独调用。
Comparator解释
class ComparatorByName implements Comparator{//实现比较器接口

        @Override
        public int compare(Object o1, Object o2) {//覆盖比较器的方法。
                Person p1 = (Person)o1;
                Person p2 = (Person)o2;
                int temp = p1.getName().compareTo(p2.getName());
                return temp==0?p1.getAge()-p2.getAge():temp;//返回值意思和上一个排序一样
               
        }

TreeSet  ts = new TreeSet(new ComparatorByName());//由于该比较器是一个单独的比较器,如果在某一个集合中使用,必须声明该集合使用的是该比较器对象。

如果一个集合既有Comparator,又有Comparable
则compartor优先级更高

作者: clp    时间: 2013-5-26 23:12
我自己和楼主一样,晕了,这里是我找到的我认为讲的比较清楚地,分享一下,希望你能用上

Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序,所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。
      Comparable此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序,类的 compareTo 方法被称为它的自然比较方法。实现此接口的对象列表(和数组)可以通过Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射表中的键或有序集合中的元素,无需指定比较器。
这两个接口和集合类本身无关,但通常和集合内的元素有关,因为集合的排序要用到它们中的方法。一个类的实例要想实现排序,必须实现Comparable,或者提供相应的Comparator。
      两者的区别:只是Comparable(可比较的)是在集合内部定义的方法实现的排序,比如,两个人要比较身高,分辨高矮是人类固有的能力,两个人只要站到一起就能分出谁高谁矮。Comparator(比较器)是在集合外部实现的排序。所以,如想实现排序,就需要在集合外定义Comparator接口的方法compare()或在集合内实现Comparable接口的方法compareTo(),Comparable是一个对象本身就已经支持自比较所需要实现的接口(如String Integer自己就可以完成比较大小操作)而Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。还有个地方就是,实现Comparable只能定义一种比较方法,但是有时候会对一个集合进行不同的排序方法,此时就可以提供别各种各样的Comparator来对集合排序,而对于要排序的元素不需要更改,所以我觉得Comparator提供了更多的灵活性。使用这种策略来比较时,如何进行比较和两个对象本身无关,而是由第三者(即比较器)来完成的。只要实现Comparator接口,任何一个对象都可能成为一个“比较器”,但比较器并不是比较自己的实例,而是比较另外两个对象,比较器在这里充当“仲裁者”的角色,这也就是为什么compare()方法需要两个参数。比如,两个人要比较谁智商更高,靠他们自身无法进行,这时要借助一个比较器(比如,智商测试题)。

作者: java.exe    时间: 2013-5-26 23:30
啊....楼上已经回答的很好了...我来说一下我自以为很通俗的一种理解方式吧.....献丑了哈   所谓的元素具有自然顺序被元素自身使用可以这样理解 如:每个人都有年龄 当Person类实现了Comparable接口在复写comparaTo()后每个Person类的实例对象都可以调用自己的这个方法和另一个人比较年龄的大小 假设有一间屋子里面有一排排的座位(也就是一个可以存储Person对象的引用的集合)我们规定按年龄从小到大依次坐下,第一个人进来的时候直接坐下 当第二个人来的时候他就自己问前面进来的你多大了得到回答后就和自己的年龄比较 然后按结果就能调整一下座次了   这也就是元素自身实现    但是如果Person类没有实现Comparable接口 Person类的对象也就没有自己去问别人的年龄然后进行比较的功能     那么我们可以给这个房子安装一个比较器 当人进房子后就去比较器里一站这个比较器能得到你的年龄并和已经在屋里的人比较并按照结果调整一下座次  这也就是所谓的集合实现。 我自己就是这样理解的 希望对你有帮助哈
作者: 花开花落总相似    时间: 2013-5-26 23:34
从字面来理解
Comparable   这个是可比较的 就是有没有比较性的意思  那理所当然的 有没有比较性 肯定是与另外一个对象相比较了所以需要覆写的方法是 compareTo
Comparator 这个是比较器的意思  也就是说  这个是要传到集合中去的  而且比较器肯定是要有2个对象才能比较了  所以这个需要覆写的是 compare

作者: 殇_心。    时间: 2013-5-27 10:11
如果问题已解决,请及时修改分类,否则继续提问,谢谢合作!
作者: 陈延真    时间: 2013-5-27 21:17
殇_心。 发表于 2013-5-27 10:11
如果问题已解决,请及时修改分类,否则继续提问,谢谢合作!

怎么修改成问题已解决?
作者: 陈延真    时间: 2013-5-27 21:19
clp 发表于 2013-5-26 23:12
我自己和楼主一样,晕了,这里是我找到的我认为讲的比较清楚地,分享一下,希望你能用上

Comparable & Com ...

谢了,嘿嘿
作者: 陈延真    时间: 2013-5-27 21:21
谢孔营 发表于 2013-5-26 22:59
Comparable:自然排序比较,被元素本身实现。
Comparator:比较器接口,用于集合实现
用程序解释更加清晰,有 ...

这个太强了。
作者: Super_Class    时间: 2013-5-28 08:56
一个是自然排序。

假设你要在TreeSet集合中存入自定义的元素。那么这个元素就要实现Comparable接口。否则没有办法进行比较

当然这个方法不是很实用。因为后期的代码修改会很麻烦。如果用不到比较的话,这个程序就显得很臃肿。

比较好的方式还是实用比较器。只要将TreeSet集合创建的时候加入比较器就可以了。这个地方相对比较简单。不要想得很难
  1. Set<Person> ts = new TreeSet<Person>(new Comparator<Person>() {
  2.                         @Override
  3.                         public int compare(Person o1, Person o2) {
  4.                                 return 1;
  5.                         }
  6.                 });
复制代码

作者: HM张博文    时间: 2013-5-28 10:14
问的好高深哦
作者: 殇_心。    时间: 2013-5-29 16:05
陈延真 发表于 2013-5-27 21:17
怎么修改成问题已解决?

点击编辑帖子  然后左上角选项中的  未解决    选择为    已解决。
就这样就行了
作者: 袁梦希    时间: 2013-5-30 10:50
楼主你好,如果帖子没问题了,那么请把帖子的类型改为“已解决”。如果不会改,请看我的个性签名




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2