Comparable & Comparator
Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序,所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。
Comparator位于包java.util下,而Comparable位于包 java.lang下
Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口)
自定义的类要在加入list容器中后能够排序,可以实现Comparable接口,在用Collections类的sort方法排序时,如果不指定Comparator,那么就以自然顺序排序,如API所说:
Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface
这里的自然顺序就是实现Comparable接口设定的排序方式。
而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。
可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。
用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
比如:你想对整数采用绝对值大小来排序,Integer 是不符合要求的,你不需要去修改 Integer 类(实际上你也不能这么做)去改变它的排序行为,只要使用一个实现了 Comparator 接口的对象来实现控制它的排序就行了。
// AbsComparator.java
import java.util.*;
public class AbsComparator implements Comparator {
public int compare(Object o1, Object o2) {
int v1 = Math.abs(((Integer)o1).intValue());
int v2 = Math.abs(((Integer)o2).intValue());
return v1 > v2 ? 1 : (v1 == v2 ? 0 : -1);
}
}
可以用下面这个类测试 AbsComparator:
// Test.java
import java.util.*;
public class Test {
public static void main(String[] args) {
//产生一个20个随机整数的数组(有正有负)
Random rnd = new Random();
Integer[] integers = new Integer[20];
for(int i = 0; i < integers.length; i++)
integers[i] = new Integer(rnd.nextInt(100) * (rnd.nextBoolean() ? 1 : -1));
System.out.println("用Integer内置方法排序:");
Arrays.sort(integers);
System.out.println(Arrays.asList(integers));
System.out.println("用AbsComparator排序:");
Arrays.sort(integers, new AbsComparator());
System.out.println(Arrays.asList(integers));
}
}
Collections.sort((List<T> list, Comparator<? super T> c)是用来对list排序的。
如果不是调用sort方法,相要直接比较两个对象的大小,如下:
Comparator定义了俩个方法,分别是 int compare(T o1, T o2)和 boolean equals(Object obj),
用于比较两个Comparator是否相等
true only if the specified object is also a comparator and it imposes the same ordering as this comparator.
有时在实现Comparator接口时,并没有实现equals方法,可程序并没有报错,原因是实现该接口的类也是Object类的子类,而Object类已经实现了equals方法
Comparable接口只提供了 int compareTo(T o)方法,也就是说假如我定义了一个Person类,这个类实现了 Comparable接口,那么当我实例化Person类的person1后,我想比较person1和一个现有的Person对象person2的大小时,我就可以这样来调用:person1.comparTo(person2),通过返回值就可以判断了;而此时如果你定义了一个 PersonComparator(实现了Comparator接口)的话,那你就可以这样:PersonComparator comparator= new PersonComparator();
comparator.compare(person1,person2);。
当需要排序的集合或数组不是单纯的数字型时,通常可以使用Comparator或Comparable,以简单的方式实现对象排序或自定义排序。
一、Comparator
强行对某个对象collection进行整体排序的比较函数,可以将Comparator传递给Collections.sort或Arrays.sort。
接口方法:
* @return o1小于、等于或大于o2,分别返回负整数、零或正整数。
*/
int compare(Object o1, Object o2);
案例:
import java.util.Comparator;
public class SampleComparator implements Comparator {
public int compare(Object o1, Object o2) {
return toInt(o1) - toInt(o2);
}
private int toInt(Object o) {
String str = (String) o;
str = str.replaceAll("一", "1");
str = str.replaceAll("二", "2");
str = str.replaceAll("三", "3");
// 
return Integer.parseInt(str);
}
/**
* 测试方法
*/
public static void main(String[] args) {
String[] array = new String[] { "一二", "三", "二" };
Arrays.sort(array, new SampleComparator());
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
二、Comparable
强行对实现它的每个类的对象进行整体排序,实现此接口的对象列表(和数组)可以通过Collections.sort或Arrays.sort进行自动排序。
接口方法:
* @return 该对象小于、等于或大于指定对象o,分别返回负整数、零或正整数。
*/
int compareTo(Object o);
假设对象User,需要按年龄排序:
private String id;
private int age;
public User(String id, int age) {
this.id = id;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
改造后的对象:
public class User implements Comparable {
private String id;
private int age;
public User(String id, int age) {
this.id = id;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int compareTo(Object o) {
return this.age - ((User) o).getAge();
}
/**
* 测试方法
*/
public static void main(String[] args) {
User[] users = new User[] { new User("a", 30), new User("b", 20) };
Arrays.sort(users);
for (int i = 0; i < users.length; i++) {
User user = users[i];
System.out.println(user.getId() + " " + user.getAge());
}
}
}
三、Comparator和Comparable的区别
先看一下使用Comparator对User集合实现排序的方式:
import java.util.Comparator;
public class UserComparator implements Comparator {
public int compare(Object o1, Object o2) {
return ((User) o1).getAge() - ((User) o2).getAge();
}
/**
* 测试方法
*/
public static void main(String[] args) {
User[] users = new User[] { new User("a", 30), new User("b", 20) };
Arrays.sort(users, new UserComparator());
for (int i = 0; i < users.length; i++) {
User user = users[i];
System.out.println(user.getId() + " " + user.getAge());
}
}
}
一个类实现了Camparable接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用sort方法排序。
Comparator可以看成一种算法的实现,将算法和数据分离,Comparator也可以在下面两种环境下使用:
1、类的设计师没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身
2、可以使用多种排序标准,比如升序、降序等
Comparable & Comparator的更多相关文章
- 【集合框架】JDK1.8源码分析之Comparable && Comparator(九)
一.前言 在Java集合框架里面,各种集合的操作很大程度上都离不开Comparable和Comparator,虽然它们与集合没有显示的关系,但是它们只有在集合里面的时候才能发挥最大的威力.下面是开始我 ...
- 给jdk写注释系列之jdk1.6容器(9)-Strategy设计模式之Comparable&Comparator接口
前面我们说TreeMap和TreeSet都是有顺序的集合,而顺序的维持是要靠一个比较器Comparator或者map的key实现Comparable接口. 既然说到排序,首先我们不用去关心什 ...
- Java学习笔记--集合元素的比较Comparable,Comparator
原文见: http://www.cnblogs.com/sunflower627/p/3158042.html 1. Comparator 和 Comparable 相同的地方 他们都是java的一个 ...
- Iterator & Iterable 和 Comparable&Comparator
java.lang.Iterator & java.lang.Iterable Iterator和Iterable的区别和联系 iterator是具有迭代状态的对象.它允许你检查它是否有更多的 ...
- Java提高十五:容器元素比较Comparable&Comparator深入分析
我们经常用容器来存放元素,通常而言我们是不关系容器中的元素是否有序,但有些场景可能要求容器中的元素是有序的,这个时候用ArrayList LinkedList Hashtable HashMap ...
- Java容器解析系列(8) Comparable Comparator
Comparable和Comparator接口是两个用于对对象进行大小比较的接口,在java集合相关类中,也被经常地使用到. 关于其使用,可以参考网络上的其他博客(没什么好说的);这里阐述关于这两个接 ...
- JDK1.8源码分析之Comparable && Comparator
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util. ...
- java容器---Comparable & Comparator
1.接口Comparable<T> API 参数类型:T ---可以与此对象进行比较的那些对象的类型 此接口强行对实现它的每个类的对象进行整体排序.这种排序被称为类的自然排序,类的c ...
- 比较器Comparable Comparator
一. Comparable Comparable 是排序接口,若一个类实现了 Comparable 接口,就意味着该类支持排序.实现了Comparable 接口的类的对象的列表或者数组可以通过 Col ...
随机推荐
- 纪念一下自己的第一篇cnblog
2016-08-1016:33:22 // Netease.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iost ...
- c++11: less的用法
less主要是重载了operator()方法,用来比较lhs 和 rhs std::less::operator() bool operator()(const T &lhs, const T ...
- 基础学习总结(八)--Intent中显示意图和隐式意图的用法
Intent(意图)主要是解决Android应用的各项组件之间的通讯.Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组 ...
- setEllipsize(TruncateAt where)
void android.widget.TextView.setEllipsize(TruncateAt where) public void setEllipsize (TextUtils.Trun ...
- Delphi 两个应用程序(进程)之间的通信
两个应用程序之间的通信实际上是两个进程之间的通信.由于本人知识有限,决定应用消息来实现.需要用到的知识: 1.RegisterWindowMessage(); //参数类型:pchar:返回值:Lon ...
- 通过js获取DropDownList的选中项
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...
- LeapMotion(2):追踪五指
上一篇文章,我们实现了Leap Motion的简单测试.追踪其中一个手指并用红色圆形表示其在空间的位置. 这篇文章,我们来实现五指的追踪. 其实,能够实现一指的追踪,那么五指的追踪自然不成问题.但是, ...
- Linux下安装firefox的flash插件
OS:ORACLE-LINUX 5.71.下载"install_flash_player_11_linux.i386.tar.gz" 包2.自己创建个目录,解压[root@b28- ...
- IOS开发之──应用之间调用(1)
iphone应用之间调用步骤: 1)在plist文件中,注册对外接口 在xcode group&files 里面,展开 resources选择<app>info.plist 鼠标右 ...
- 【学习总结】【多线程】 安全隐患 & 通讯 & 线程的状态
一.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数 ...