黑马程序员技术交流社区

标题: 关于Comparable和Comparator的用法 [打印本页]

作者: 陈雨    时间: 2013-4-15 10:59
标题: 关于Comparable和Comparator的用法
本帖最后由 陈雨 于 2013-4-16 08:08 编辑

      有点弄不清到底什么时候用Comparable和Comparator。毕老师的视疲里讲当元素自己具备比较性时用Comparable,当元素不具备比较性,或者排序的方式不是自己想要的就用Comparator。我想问什么时候就叫元素自身不具备比较性?当用TreeSe和TreeMap集合时?还是说元素自己本身的特性,比如自然顺序(数字,字母啊),这时他们自己就具备比较性吗?
作者: mvplee    时间: 2013-4-15 11:05
在简单Java类设计之初,如果考虑到需要排序、比较,简单Java类实现Comparable接口,在类的内部具有了比较规则。
Comparator也是比较器,你可以理解为“挽救”的比较,原类不觉被比较规则,需要类似于“第三方”提供比较规则,就使用Comparator。
这些都是纯概念性的,内部实现比较规则都是一样的。!

作者: 殇_心。    时间: 2013-4-15 11:08
举个例子吧:
比如说人和人比较的时候。
这个很抽象吧? 到底比较什么,或者说没有比较性可言。
这个时候你就可以定义你的比较方式,如年龄。
当年龄一样的时候,又该按什么比较啊。 这种情况下就用Comparator比较器。
作者: 刘永建    时间: 2013-4-15 11:28
你要搞清楚,Comparable和Comparator都是用来比较的接口,它们常常被用在自定义类型中,也就是设计自己的比较方法
作为接口的代表 interface Comparable 接口:
Arrays类中的sort方法承诺可以对对象数组进行排序,但要求对象所属的类必须实现了 Comparable接口,并且重写了其中的comparaTo方法
而对于Comparator接口,需要重写其中的compar方法,当然TreeSet是有序的,这需要你在生成对象的时候传入一个实现了Comparator接口的对象,
作为比较的依据;
希望对你有帮助,不懂得话可以再联系我!
大家一起加油!

作者: 本人已死    时间: 2013-4-15 11:45
public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
public class TreeMap<K,V>extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, Serializable基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
因为treeset,treemap实现了Comparator 所以具有排序的特性
Comparable排序都都是一些已有的类的对象
而我们一般自己写的类的对象需要按我们自己的方式排序就需要Comparator 来实现,通过复写compare() 和equals()方法

作者: gerenvip    时间: 2013-4-15 11:48
这个主要清楚分别用在什么地方,就很容易明白:
TreeSet我们知道可以对Set集合中的元素进行排序
而排序有两种方法:
1.让元素自身具有比较性,举个例子。我们知道Person类的对象是不具备比较性的,而我们又需要对对象进行排,所以我们可以人为的定义,让对象具有比较性。明白这一点后,就好似怎么实现可比较性了。这时第一种方法就出现了。让Person类实现comparable接口,覆盖接口中的compareTo方法
这种方式也叫做元素的自然排序,或者叫做默认顺序。
所谓元素自身不具备比较性,其实很好理解。例如两个人有比较性吗?没有,要比较也得是你定义比较规则,例如谁年龄长,谁身高高,谁挣钱多。等等。
正是由于对象没有比较性,所以我们才在类中定义比较性,让其具有可比较性。这就是TreeSet实现排序的第一种方式。当时这种方式仅限于同类对象进行比较,例如人和人比较,但是实现不同类型的对象比较时,这种方法就不行了。
Treeset中的第二种比较方式,比较通用。我们知道,如果对象元素不具备比较性,我们可以让装它的容器具备可比较性。这就是第二种方法的出发点。
实现方法是:
定义一个类,实现Comparetor接口,覆盖compare方法。

使用时要想分清到底使用什么方法。首先看你的比较对象元素时什么类型的。一般使用第二种,即比较器
注意要记住:
Comparetor中是compare方法
而Comparable中是compareTo方法
希望能帮到你。
给一个毕老师视频中的例子:
  1. class  TreeSetDemo2
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 TreeSet ts = new TreeSet(new MyCompare());
  6.                 //使用构造器TreeSet(Comparator<? super E> comparator)
  7.                 ts.add(new Student("lisi03",22));
  8.                 ts.add(new Student("lisi02",20));
  9.                 ts.add(new Student("lisi09",19));
  10.                 ts.add(new Student("lisi01",18));
  11.                 ts.add(new Student("lisi01",18));

  12.                 Iterator it= ts.iterator();
  13.                 while(it.hasNext())
  14.                 {
  15.                         Student p = (Student)it.next();
  16.                         sop(p.getName()+"..."+p.getAge());
  17.                 }
  18.         }
  19.         public static void sop(Object obj)
  20.         {
  21.                 System.out.println(obj);
  22.         }
  23. }

  24. class MyCompare implements Comparator
  25. {
  26.         public int compare(Object o1,Object o2)
  27.         {
  28.                 Student s1= (Student)o1;
  29.                 Student s2= (Student)o2;

  30.                 int num = s1.getName().compareTo(s2.getName());
  31.                 if(num==0)
  32.                 {
  33.                         return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
  34.                         /*
  35.                         if(s1.getAge()>s2.getAge())
  36.                                 return 1;
  37.                         if(s1.getAge()==s2.getAge())
  38.                                 return 0;
  39.                         return -1;
  40.                         */
  41.                 }
  42.                 return num;
  43.         }
  44. }
  45. class Student implements Comparable//该接口强制让学生具备可比性
  46. {
  47.         private String name;
  48.         private int age;
  49.         Student(String name,int age)
  50.         {
  51.                 this.name=name;
  52.                 this.age=age;
  53.         }
  54.         public String getName()
  55.         {
  56.                 return name;
  57.         }
  58.         public int getAge()
  59.         {
  60.                 return age;
  61.         }

  62.         public int compareTo(Object obj)//覆盖的方法不能声明
  63.         {
  64.                 if(!(obj instanceof Student))
  65.                         throw new RuntimeException("不是学生对象");
  66.                 Student s= (Student)obj;
  67.                 System.out.println(this.name+"..compareto.."+s.name);

  68.                 if (this.age>s.age)
  69.                         return 1;
  70.                 if(this.age==s.age)
  71.                 {
  72.                         return this.name.compareTo(s.name);
  73.                 }
  74.                 return -1;
  75.         }

  76. }
复制代码

作者: gerenvip    时间: 2013-4-15 11:52
gerenvip 发表于 2013-4-15 11:48
这个主要清楚分别用在什么地方,就很容易明白:
TreeSet我们知道可以对Set集合中的元素进行排序
而排序有两 ...

不好意思,很多错别字,将就着看哈,呵呵!
作者: _王涛    时间: 2013-4-15 13:04
Comparator接口,在使用时,也就是所要排序的集合不具备比较性,或具备比较性,但不是我们想要的时候,就可以用子类去实现Colparator接口,并且实现compare方法,创建一个比较器。
comparable接口,是元素在不具备比较性的时候,我们可以强制让对象具备比较性,并实现compareTo方法,当前这个对象与指定对象进行顺序比较。当该对象小于、等于或大于指定对象时,分别返回一个负整数、零或者正整数。




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