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接口实现后便不能改动。

总结:

comparator接口:真正要实现的只有compare()方法,需要单独准备出一个类来实现comparator接口,这个类将作为指定类的排序类

public int compare(Emp o1,Emp,o2){

return o1.id - o2.id

}

这是说如果o1的id - o2的id是正数就升序,如果负数降序。如果0就剔除

>=1  升序

<=-1 降序

=0 重复,不记录

comparable接口

实现该类接口不需要重新创建一个排序的类,使用接口compareble接口排序,只要重写里面的compareTo()方法

Collections类是一个包装类,它包含有各种有关集合操作的静态方法。就像一个工具类。

Collections.sort()

sort()排序方法,根据元素的自然排序对指定列表按升序进行排序

public static <T>void sort(List<T> list,Comparator<>),根据指定比较器产生的顺序对指定列表进行排序,此列表内的所有元素都必须可使用指定的比较器相互比较

参数:list——要排序的列表

C——确定列表顺序的比较器

在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。

通常对象之间的比较可以从两个方面去看:

第一个方面:对象的地址是否一样,也就是是否引用自同一个对象。这种方式可以直接使用“==“来完成。

第二个方面:以对象的某一个属性的角度去比较。

从最新的JDK8而言,有三种实现对象比较的方法:

一、覆写Object类的equals()方法;

二、继承Comparable接口,并实现compareTo()方法;

三、定义一个单独的对象比较器,继承自Comparator接口,实现compare()方法。

由于使用的排序方式的不同,具体选择哪种方法来实现对象的比较也会有所不同。

覆写equals()方法,一般用于自己实现对象数组排序的情况,而对于要使用java内置的排序算法时,使用后面两种方式都是可行的。

先来看第二种方式,这种方式就是让自己编写的类继承Comparable接口,并实现compareTo()方法,这种情况下,在使用java.util.Arrays.sort()

方法时,不用指定具体的比较器,sort()方法会使用对象自己的比较函数来完成对象的排序。下面是一个具体的例子:

[java] view plain copy

import java.util.Arrays;

class BookCook implements Comparable<BookCook>{

private String title;

private double price;

public BookCook(String title,double price){

this.title = title;

this.price = price;

}

@Override

public String toString() {

return "书名:"+this.title+",价格:"+this.price;

}

@Override

public int compareTo(BookCook o) {

if(this.price > o.price){

return 1;

}else if(this.price < o.price){

return -1;

}else{

return 0;

}

}

}

一般我们使用以上两种方法就能够满足实际的开发问题。但是当出现以下情况时,就需要用到Comparator接口:

要在已经开发好的代码的基础上完善对象的比较功能时,又不想更改之前的代码,这种情况下,从JDK1.8之后出现了Comparator接口,是对这种情况的一个弥补。

这种情况下,我们需要单独定义一个对象比较器,继承Comparator接口,并实现compare()方法。示例代码如下:

[java] view plain copy

class Student {

private String name;

private double score;

public Student(String name,double score){

this.name = name;

this.score = score;

}

public double getScore(){

return this.score;

}

@Override

public String toString() {

return "姓名:"+this.name+",分数:"+this.score;

}

}

class StudentComparator implements Comparator<Student> {

@Override

public int compare(Student o1,Student o2) {

if(o1.getScore() > o2.getScore()){

return 1;

}else if(o1.getScore() < o2.getScore()){

return -1;

}else{

return 0;

}

}

}

public class TestComparator {

public static void main(String[] args) {

Student[] sts = new Student[]{

new Student("小戴",60),

new Student("小王",90),

new Student("老王",80),

new Student("小萱",95)

};

java.util.Arrays.sort(sts, new StudentComparator());

System.out.println(java.util.Arrays.toString(sts));

}

}

Java中存在比较运算符:> 、< 、>=、<=、!=、==、instanceof

只能比较基本数据类型,如果对于对象无法进行比较,如果在对象中需要实现对象之间的比较,只能通过Comparable、Compartor接口实现

(1) Comparable接口(自然排序)

String、包装类都已经默认实现了mt4下载教程Comparable接口,并重写了int compareTo(T o)方法(定义排序规则),所以String、包装类都是可以进行排序的

默认是按照升序进行排序的

int compareTo(T o)

如果返回值是正数,代表调用者(this)的值比o的值要大

如果返回值是负数,代表调用者(this)的值比o的值要小

如果返回值是0,代表调用者(this)的值比o的值相等

如果一个自定义类需要实现排序功能,需要让当前类实现Comparable接口,重写int compareTo(T o)方法,在该方法中重写排序的规则

如果一个类一旦实现了Comparable接口,那么这个类的对象在任意地方都可以进行排序或者比较

/*

String、包装类都已经默认实现了Comparable接口,并重写了int compareTo(T o)方法

*/

public class CompareDemo {

public static void main(String[] args) {

int[] arr = {5,4,2,1,3};

Arrays.sort(arr);

System.out.println(Arrays.toString(arr));

String[] s = {"AA","CC","ZZ","BB","JJ"};

Arrays.sort(s);

System.out.println(Arrays.toString(s));

}

}

/*

对象之间比较

*/

public class CompareDemo {

public static void main(String[] args) {

Employee[] e = new Employee[5];

e[0] = new Employee("e001","Jack","d001");

e[1] = new Employee("e005","Tom","d010");

e[2] = new Employee("e010","Jack","d011");

e[3] = new Employee("e004","Rose","d005");

e[4] = new Employee("e009","Marry","d008");

Arrays.sort(e);

System.out.println(Arrays.toString(e));

}

}

class Employee implements Comparable<Employee>{

private String eno;

private String ename;

private String dept;

public String getEno() {

return eno;

}

public void setEno(String eno) {

this.eno = eno;

}

public String getEname() {

return ename;

}

public void setEname(String ename) {

this.ename = ename;

}

public String getDept() {

return dept;

}

public void setDept(String dept) {

this.dept = dept;

}

public Employee(String eno, String ename, String dept) {

super();

this.eno = eno;

this.ename = ename;

this.dept = dept;

}

public Employee() {

super();

}

@Override

public String toString() {

return "Employee [eno=" + eno + ", ename=" + ename + ", dept=" + dept + "]";

}

@Override

public int compareTo(Employee o) {

//借助String的compareTo方法

return this.eno.compareTo(o.eno);

}

}

(2)Comparator接口(定制排序)

如果一个类没有实现Comparable接口,但是这个类又不方便实现Comparable接口(开闭原则),或者一个类已经实现了Comparable接口,但是其中的compareTo不满足我们的需求,那么我们可以使用Comparator接口方式进行定制排序

默认升序

int compare(T o1,T o2)

o1>o2 返回正数

o1<o2 返回负数

o1==o2 返回0

public class CompareDemo {

public static void main(String[] args) {

Employee[] e = new Employee[5];

e[0] = new Employee("e001","Jack","d001");

e[1] = new Employee("e003","Tom","d010");

e[2] = new Employee("e003","Jack","d011");

e[3] = new Employee("e004","Rose","d005");

e[4] = new Employee("e002","Marry","d008");

Arrays.sort(e, new Comparator<Employee>() {

@Override

public int compare(Employee o1, Employee o2) {

if(o1.getEno().compareTo(o2.getEno())!=0) {

return o1.getEno().compareTo(o2.getEno());

}else {

return -o1.getEname().compareTo(o2.getEname());

}

}

});

System.out.println(Arrays.toString(e));

}

}

class Employee {

private String eno;

private String ename;

private String dept;

public String getEno() {

return eno;

}

public void setEno(String eno) {

this.eno = eno;

}

public String getEname() {

return ename;

}

public void setEname(String ename) {

this.ename = ename;

}

public String getDept() {

return dept;

}

public void setDept(String dept) {

this.dept = dept;

}

public Employee(String eno, String ename, String dept) {

super();

this.eno = eno;

this.ename = ename;

this.dept = dept;

}

public Employee() {

super();

}

@Override

public String toString() {

return "Employee [eno=" + eno + ", ename=" + ename + ", dept=" + dept + "]";

}

}

java常用类——比较器的更多相关文章

  1. java常用类 比较器/system/math/big

    Java 比较器 自然排序:java.lang.Comparable 定制排序:java.util.Comparator 自然排序:java.lang.Comparable  Comparable接口 ...

  2. Java基础 —— Java常用类

    Java常用类: java.lang包: java.lang.Object类: hashcode()方法:返回一段整型的哈希码,代表地址. toString()方法:返回父类名+"@&quo ...

  3. Java常用类学习笔记总结

    Java常用类 java.lang.String类的使用 1.概述 String:字符串,使用一对""引起来表示. 1.String声明为final的,不可被继承 2.String ...

  4. Java 常用类总结(SE基础)

    本篇博客对java常用类相关知识进行了归纳总结,比较详细,适用于学习和复习. 1. 字符串相关的类 1.1 String String是一个final类,代表不可变的字符序列.不可被继承. Strin ...

  5. Java常用类的使用

    Java常用类 1. Optional 在我们的开发中,NullPointerException可谓是随时随处可见,为了避免空指针异常,我们常常需要进行 一 些防御式的检查,所以在代码中常常可见if( ...

  6. Java常用类之要点总结

    Java常用类之要点总结

  7. Java常用类:包装类,String,日期类,Math,File,枚举类

    Java常用类:包装类,String,日期类,Math,File,枚举类

  8. Java常用类笔记(学习尚硅谷java基础教程)

    一.Java根类Object类1.toString()方法 1)以文本对象返回,故toString()的定义为public String toString() {} 2)默认的字符串输出是:包.类名@ ...

  9. Java常用类之String类、Stringbuffer和Random类练习

    定义一个StringBuffer类对象, 1)使用append方法向对象中添加26个字母,并倒序遍历输入 2)删除前五个字符 package 第十一章常用类; /** * 定义一个StringBuff ...

随机推荐

  1. Linux——用户及文件权限管理

    2019-07-31 用户管理 查看用户 who am i:打开当前伪终端的用户的用户名 pts/0 后面那个数字就表示打开的伪终端序号,你可以尝试再打开一个终端,然后在里面输入 who am i , ...

  2. 使用ReadStream方法读取文件事件传递过程

    const fs = require('fs'); let file = fs.createReadStream("filename.js"); file.on("ope ...

  3. Docker拉取镜像时错误解决办法

    拉取docker中的镜像时报错: [root@master ~]# docker pull docker.io/centos:latest Trying to pull repository dock ...

  4. Packet for query is too large (1986748 > 1048576). You can change this value on the server by 异常

    场景:mybatis动态拼接,批量添加数据,因为数据太多,凭借过多,导致MySql数据库中插入大于1m的数据时,提示该异常. 解决办法:修改mysql的属性 max_allowed_packet即可. ...

  5. 设计不严谨 - Get参数传日期空格未转义字符出现截断请求,后端无法处理

    设计不严谨 Get参数传递日期的时候有空格,如果未转义的话,会截断请求,然后后端无法处理. 从业务场景看 从产品的角度看,产品想要看每个活动的效果,而不是想知道技术. 角度不同,视觉不同 mark

  6. Shiro学习(18)并发人数限制

    在某些项目中可能会遇到如每个账户同时只能有一个人登录或几个人同时登录,如果同时有多人登录:要么不让后者登录:要么踢出前者登录(强制退出).比如spring security就直接提供了相应的功能:Sh ...

  7. php编译安装phalcon框架 - centos

    使用官方的文档安装方式会报错,进行了一些实验,终于安装成功! 安装phalcon前提是需要安装php的pdo,如果使用mysql 需要安装 pdo_mysql 先看下git的版本号git --vers ...

  8. Android_开发片段(Part 2)

    1.List和Map知识: 1)如何定义 List<Map<String,Object>> list=new ArrayList<Map<String,Object ...

  9. tp U函数 logs

    注意 U 函数 项目今天已经搞定了本以为可以上线了没问题了,但是 当我把tp调试模式关闭后:      define('APP_DEBUG',false); 页面完全加载不出来,于是开启:  'SHO ...

  10. jmeter 参数化3种

    一.利用函数助手获取参数值 选项->函数助手对话框 __CSVRead, __Random, 生成的函数字符串:${__Random(,,)}第一个参数为随机数的下限,第二个参数为随机数的上限, ...