Java比较器

前言

本篇文章主要介绍的是Java比较器的实现与测试。

1.java.lang.Comparable排序接口

定义:

| :------------: | :------------: |
Comparable是排序接口。若一个类实现了Comparable接口,就意味着该类支持排序。实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。

Comparable接口中的方法:

| 接口中的方法 | 说明 |
| int compareTo(T t) | 比较当前对象与传入进来对象的大小|
| |参数:t 表示要比较的对象,返回值:如果当前的对象大于t,返回正整数。如果当前的对象等于t,返回0。如果当前对象小于t,返回负整数 |
这是Java的一种约定,当排序的sort()方法在对集合中的元素两两进行比较的时候会调用我们实现的compareTo(T t)方法。如果compareTo()返回正整数,则表示当前元素大于和它比较的元素;如果返回负整数则表示当前元素小于和它比较的元素;如果返回0,则表示两者相等。

案例
//实体类实现Comparable接口
@Data
public class Record implements Comparable<Record> {
    private String name;
    private int num;

    public Record(String name,int num) {
        this.name = name;
        this.num = num;
    }
    @Override
    public String toString() {
        return "("+name+","+num+")";
    }
    
    //重写compareTo方法,方法内定义排序规则
    @Override
    public int compareTo(Record r) {
        //1.name属性字符串类型比较unicode值
        return this.name.compareTo(r.name);
------------
        //2.price属性数值类型比较大小
        if(this.num > r.num){
            return 1;
        }else if(this.num < r.num){
            return -1;
        }else{
            return 0;
        }
------------
        //3.price属性数值类型比较大小
        return this.num - r.num;
------------
        //4.price属性包装类比较大小
        return Integer.compare(this.num, r.getNum());
------------
        //5.name属性字符串类型按照拼音字母进行排序
        return Collator.getInstance(Locale.CHINA).compare(this.name,r.name);
    }
}

针对最后一种排序规则,jdk自带的Collator包涵的汉字太少了,对一些生僻的姓氏不能进行排序。Collator推荐使用:import com.ibm.icu.text.Collator;
pom依赖:

<dependency>
    <groupId>com.ibm.icu</groupId>
    <artifactId>icu4j</artifactId>
    <version>57.1</version>
</dependency>
测试:
    @Test
    public void test2() {
        ArrayList<Record> list = new ArrayList<>();
        //添加元素到list
        Collections.addAll(list,
        new Record("日本",1),
        new Record("印尼",4),
        new Record("菲律宾",2),
        new Record("中国",5),
        new Record("中国香港",3),
        new Record("斐济",6));
        //排序前输出
        System.out.println(list);
        //[(日本,1), (印尼,4), (菲律宾,2), (中国,5), (中国香港,3), (斐济,6)]
        //排序
        Collections.sort(list);
        //排序后输出
        System.out.println(list);
        //1.[(中国,5), (中国香港,3), (印尼,4), (斐济,6), (日本,1), (菲律宾,2)]
        //2、3、4.[(日本,1), (菲律宾,2), (中国香港,3), (印尼,4), (中国,5), (斐济,6)]
        //5.[(菲律宾,2), (斐济,6), (日本,1), (印尼,4), (中国,5), (中国香港,3)]
    }

2.java.util.Comparator比较器接口

定义:

Comparator是比较接口,我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过实现Comparator来新建一个比较器,然后通过这个比较器对类进行排序。

Comparable接口中的方法:
接口中的方法 说明
int compare(T t1, T t2) 比较t1和t2这两个对象,如果:t1 > t2,这个方法返回正整数;t2 == t1,返回0;t1 < t2,这个方法返回负整数
案例
//创建实体类
@Data
public class Record{
    private String name;
    private int num;

    public Record(String name,int num) {
        this.name = name;
        this.num = num;
    }

    @Override
    public String toString() {
        return "("+name+","+num+")";
    }
}
//测试
public class Demo {
    @Test
    public void test() {
        List<Record> list = new ArrayList<>();
        Collections.addAll(list,
        new Record("日本",1),
        new Record("印尼",4),
        new Record("菲律宾",2),
        new Record("中国",5),
        new Record("中国香港",3),
        new Record("斐济",6));
        System.out.println(list);
        //使用比较器中的排序规则进行排序
        Collections.sort(list,new NameComparator());
        System.out.println(list);
        Collections.sort(list,new NumComparator());
        System.out.println(list);
        //以上输出
        //[(日本,1), (印尼,4), (菲律宾,2), (中国,5), (中国香港,3), (斐济,6)]
        //[(菲律宾,2), (斐济,6), (日本,1), (印尼,4), (中国,5), (中国香港,3)]
        //[(日本,1), (菲律宾,2), (中国香港,3), (印尼,4), (中国,5), (斐济,6)]
    }
}

//名称比较器,按汉字拼音顺序
class NameComparator implements Comparator<Record> {
    @Override
    public int compare(Record r1, Record r2) {
        return Collator.getInstance(Locale.CHINA).compare(r1.getName(),r2.getName());
    }
}
//数字比较器,按大小
class NumComparator implements Comparator<Record> {
    @Override
    public int compare(Record r1, Record r2) {
        return r1.getNum() - r2.getNum();
    }
}

使用匿名内部类形式实现Comparator接口

public class Demo {
    @Test
    public void test() {
        List<Record> list = new ArrayList<>();
        Collections.addAll(list,
        new Record("日本",1),
        new Record("印尼",4),
        new Record("菲律宾",2),
        new Record("中国",5),
        new Record("中国香港",3),
        new Record("斐济",6));
        System.out.println(list);
        Collections.sort(list, new Comparator<Record>() {
            @Override
            public int compare(Record r1, Record r2) {
                return Collator.getInstance(Locale.CHINA).compare(r1.getName(),r2.getName());
            }
        });
        System.out.println(list);
        //使用比较器中的排序规则进行排序
        Collections.sort(list, new Comparator<Record>() {
            @Override
            public int compare(Record r1, Record r2) {
                return r1.getNum()-r2.getNum();
            }
        });
        System.out.println(list);
        //以上输出
        //[(日本,1), (印尼,4), (菲律宾,2), (中国,5), (中国香港,3), (斐济,6)]
        //[(菲律宾,2), (斐济,6), (日本,1), (印尼,4), (中国,5), (中国香港,3)]
        //[(日本,1), (菲律宾,2), (中国香港,3), (印尼,4), (中国,5), (斐济,6)]
    }
}

3.Comparable和Comparator区别比较

Comparable 和 Comparator 都是用来实现集合中的排序的,只是 Comparable 是在对象内部定义的方法实现的排序,Comparator 是在集合外部实现的排序。

1.Comparable位于包java.lang下,Comparator位于包java.util下。Comparable接口将比较代码嵌入自身类中,而Comparable在一个独立的类中实现比较。

2.如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过Comparator 来实现比较算法进行排序。

3.Comparator为了使用不同的排序规则做准备。比如:升序、降序或按不同的属性进行排序。

4.注

字符串比较的规则:
从字符串的第1个字符开始比较大小,比较它们的ASCII码值。如果第1个字符相等,则比较第2个字符。依次类推,直到比较出大小为止。
如果是汉字,则比较Unicode值。

CSDN:https://blog.csdn.net/qq_27682773
简书:https://www.jianshu.com/u/e99381e6886e
博客园:https://www.cnblogs.com/lixianguo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容