java中Comparable和Comparator两种比较器的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中Comparable和Comparator两种比较器的区别相关的知识,希望对你有一定的参考价值。

Comparable和Comparator接口都是为了对类进行比较,众所周知,诸如Integer,double等基本数据类型,java可以对他们进行比较,而对于类的比较,需要人工定义比较用到的字段比较逻辑。可以把Comparable理解为内部比较器,而Comparator是外部比较器,基本的写法如下:
class Apple implements Comparable<Apple>
int id;
double price;

public Apple(int id, double price)
this.id = id;
this.price = price;

public int compareTo(Apple o)
//return Double.compare(this.getPrice(),o.getPrice());
if (Math.abs(this.price-o.price)<0.001)
return 0;
else
return (o.price-this.price)>0?1:-1;

@Override
public String toString()
return "Apple" +
"id=" + id +
", price=" + price +
'';


class AESComparator implements Comparator<Apple>

public int compare(Apple o1, Apple o2)
if (Math.abs(o1.price-o2.price)<0.001)
return 0;
else
return (o1.price-o2.price)>0?1:-1;



实现了Comparable接口的类需要实现compareTo()方法,传入一个外部参数进行比对,实现了Comparator接口的方法需要实现compare()方法,对外部传入的两个类进行比较,从而让外部方法在比较时调用。
两者的区别是实现Comparator接口代码更加灵活,可以定义某个类的多个比较器,从而在排序时根据实际场景自由调用,而Comparable接口实现后便不能改动。两种接口的调用方式如下:
class AESComparator implements Comparator<Apple>

public int compare(Apple o1, Apple o2)
if (Math.abs(o1.price-o2.price)<0.001)
return 0;
else
return (o1.price-o2.price)>0?1:-1;



class DESComparator implements Comparator<Apple>

public int compare(Apple o1, Apple o2)
if (Math.abs(o1.price-o2.price)<0.001)
return 0;
else
return (o1.price-o2.price)>0?-1:1;



public static void main(String[] args)
Apple apple1 = new Apple(1,4.8);
Apple apple2 = new Apple(2,5.9);
Apple apple3 = new Apple(3,8.5);
List<Apple> list = new ArrayList<Apple>();
list.add(apple1);
list.add(apple3);
list.add(apple2);
System.out.println("Comparable==========");
System.out.printf("this list of apples: %s\n",list);
Collections.sort(list);
System.out.printf("this list of apples: %s\n",list);
System.out.println("Comparator==========");
System.out.printf("this list of apples: %s\n",list);
Collections.sort(list,new DESComparator());
System.out.printf("this list of apples: %s\n",list);
Collections.sort(list,new AESComparator());
System.out.printf("this list of apples: %s\n",list);




上述代码存在的问题,不能在比较器中进行double类型的减法操作,因为对于值比较大的double,减法操作容易导致值的溢出,java7对每一种包装类型的比较新增了compare()方法,改造后的代码如下:
class Apple implements Comparable<Apple>
int id;
double price;

public Apple(int id, double price)
this.id = id;
this.price = price;

public int compareTo(Apple o)
return Double.compare(this.price,o.price);

@Override
public String toString()
return "Apple" +
"id=" + id +
", price=" + price +
'';


class AESComparator implements Comparator<Apple>

public int compare(Apple o1, Apple o2)
return Double.compare(o1.price,o2.price);


class DESComparator implements Comparator<Apple>

public int compare(Apple o1, Apple o2)
return Double.compare(o2.price,o1.price);


查看Double.compare的源码如下
public static int compare(double d1, double d2)
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger

// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
参考技术A Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序,所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。

Java集合-案例

1、ArrayList集合中,contains重写:

2、Vector使用枚举遍历集合

3、List集合特有的迭代器

4、HashSet集合,存储自定义数据类型,要求重写hashCode()和equals()方法

 

5、TreeSet集合存储自定义数据类型,重写比较

comparable接口:comparaTo方法:

Comparator接口:

6、Collections工具类:

7、遍历Map集合:

1、

2、

 

以上是关于java中Comparable和Comparator两种比较器的区别的主要内容,如果未能解决你的问题,请参考以下文章

[java]Comparable和Comparator

Comparator

Comparable接口

集合框架(TreeSet原理)

Java集合-案例

自然排序Comparable的使用