文档章节

似懂非懂 Comparable和 Comparator

TSMYK
 TSMYK
发布于 2018/09/29 10:51
字数 1303
阅读 1464
收藏 28

在java中提供了两种排序方式:Comparable和 Comparator,它们两个看起来非常的相似,在不是很了解的情况下不知道如何使用,什么情况下使用哪个进行排序,接下来就看下它们的一个区别和使用方式:

Comparable

首先看下 Comparable,Comparable 它可以看成是一个排序接口,一个类实现了该接口,就表示该类本身具有排序的功能,如果对该类的集合或者数组进行排序,则可以使用 Collections.sort() 和 Arrays.sort() 进行排序而不用再指定额外的比较器;

此外,实现了该接口的类,也可以作为 SortedMap 和 SortedSet 的 key 也不用再指定额外的比较器, 但是,如果需要把实现了该接口的类当作 SortedMap 的 Key 或者 放入到  SortedSet 中,需要保证 e1.compareTo(e2) == 0 和 e1.equals(e2) 相等,

但是有一点需要注意的是:因为 e.equal(null) 会返回false,所以,当我们需要比较的对象为 null 的时候,应该抛出一个 空指针异常。

接下来看下 Comparable 接口的方法,该接口下只有一个方法:

public int compareTo(T o);

该接口返回一个 int 类型,有三种情况:

若 e1 > e2 则 e1.compateTo(e2) > 0,返回正数

若 e1 = e2 则 e1.compateTo(e2) = 0,返回0

若 e1 < e2 则 e1.compateTo(e2) < 0,返回负数

接下来看下如何使用:

首先定义一个类实现该接口,之后重写 compareTo() 方法,一般也需要重写 equal()  和 hashcode() 方法:

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Comparable<User> {

    private String name;

    private int age;

    private String job;

    @Override
    public int compareTo(User o) {
        return getName().compareTo(o.getName());
    }

    @Override
    public int hashCode() {
        return getName().hashCode() * 31 + getAge();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj){
            return true;
        }
        if (! (obj instanceof User)){
            return false;
        }
        User u = (User)obj;
        return (getName().equals(u.getName())) && (getAge() == u.getAge()) && (getJob().equals(u.getJob()));
    }
}

接下来就可以对 该类进行排序了:

首先创建该对象的一个集合:


        User u1 = new User("zhangsan", 28, "C++");
        User u2 = new User("zhangsan", 28, "C++");
        User u3 = new User("wangwu", 22, "C");
        User u4 = new User("xiaoliu", 26, "Python");
        User u5 = new User("jiqjiq", 11, "Go");

        System.out.println(u1.equals(u2)); // true
        System.out.println(u1.compareTo(u2) == 0); // true

        List<User> users = Lists.newArrayList(u1, u2, u3, u4, u5);

之后,可以使用   Collections.sort() 和 Arrays.sort() 进行排序,而不用再指定额外的比较器了:

        System.out.println("排序之前...........");
        users.forEach((u) -> System.out.println(u));
        
        // 排序
        Collections.sort(users);

        System.out.println("排序之后...");
        users.forEach((u) -> System.out.println(u));

结果:
排序之前...........
User(name=zhangsan, age=28, job=C++)
User(name=zhangsan, age=28, job=C++)
User(name=wangwu, age=22, job=C)
User(name=xiaoliu, age=26, job=Python)
User(name=jiqjiq, age=11, job=Go)
排序之后...
User(name=jiqjiq, age=11, job=Go)
User(name=wangwu, age=22, job=C)
User(name=xiaoliu, age=26, job=Python)
User(name=zhangsan, age=28, job=C++)
User(name=zhangsan, age=28, job=C++)

之后,还可以把这些对象放入到 SortedSet 中,就会自然对这些对象进行排序:

TreeSet<User> treeSet = new TreeSet<>(users);

treeSet.forEach((user -> System.out.println(user)));

结果:

User(name=jiqjiq, age=11, job=Go)
User(name=wangwu, age=22, job=C)
User(name=xiaoliu, age=26, job=Python)
User(name=zhangsan, age=28, job=C++)

因为 Set 中没有重复元素,所有会过滤掉重复的元素。

在java的核心类库中,一些类已经实现该接口,所以可以直接对应它们进行排序,如 String , Integer 等:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence 

public final class Integer extends Number implements Comparable<Integer> 


List<String> strings = Lists.newArrayList("c", "e", "a", "b", "d");
Collections.sort(strings);

List<Integer> integers = Lists.newArrayList(3, 2, 4, 1, 5);
Collections.sort(integers);

Comparator

Comparator 可以把它看成是一个比较器接口,它是一个比较器,实现该接口的类本身没有比较的功能,只是用它去对其他的元素进行排序:

Comparator 接口有两个方法:

int compare(T o1, T o2);
boolean equals(Object obj);
 

还有一些默认的方法,都是一些 java8 中的方法,

自定义一个比较器:

public class UserSortByName implements Comparator<User1> {

    @Override
    public int compare(User1 o1, User1 o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

之后就可以使用该自定义的比较器对集合进行排序:

 List<User1> users1 = Lists.newArrayList(u11, u21, u31, u41, u51);
 Collections.sort(users1, new UserSortByName());

当然,也可以不用自定义一个比较器,直接使用匿名类即可,如下:

        // 排序
        Collections.sort(users1, new Comparator<User1>() {
            @Override
            public int compare(User1 o1, User1 o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

        // lambda 表达式的写法:

        Collections.sort(users1, Comparator.comparing(User1::getName));


        // 添加到 SortedSet 中
        TreeSet<User1> treeSet1 = new TreeSet<>(new Comparator<User1>() {
            @Override
            public int compare(User1 o1, User1 o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        treeSet1.addAll(users1);
        
        // lambda 表达式写法
        TreeSet<User1> treeSet2 = new TreeSet<>(Comparator.comparing(User1::getName));
        treeSet2.addAll(users1);

总结:

Comparable 它是一个排序接口,实现该接口的类本身具有排序的功能,可以直接使用 Collections.sort() 和 Arrays.sort() 进行排序而不用再指定额外的比较器;也可以直接放入到 SortedSet 和 SortedMap 中的保证其有序;

Comparator 它是一个比较器,实现该接口的类只能用其对其他对象进行排序;

Comparable 更多的像一个内部比较器,而 Comparator  更多的像一个外部比较器

 

 

© 著作权归作者所有

TSMYK
粉丝 101
博文 84
码字总数 207009
作品 0
成都
程序员
私信 提问
Java 中 Comparable 和 Comparator 比较

本文,先介绍Comparable 和Comparator两个接口,以及它们的差异;接着,通过示例,对它们的使用方法进行说明。 Comparable 简介 Comparable 是排序接口。 若一个类实现了Comparable接口,就意...

foxeye
2016/03/01
75
0
Comparable与Comparator的区别

前几天在项目中遇到了一个将复杂对象进行排序的问题:计算BingMap地图上距离当前位置5KM内发生事故(TrafficIncident)的点到当前位置的距离,并按距离升序排序。距离都算出来了,但这些Tra...

摆渡者
2014/04/12
981
0
Comparable 和 Comparator 的区别

Java 中为我们提供了两种比较机制:Comparable 和 Comparator,他们之间有什么区别呢?今天来了解一下。 Comparable 自然排序 Comparable 在 java.lang 包下,是一个接口,内部只有一个方法 ...

Adel
2016/12/13
38
0
java底层比较器Comparable和Comparator比较对象时的使用

刚开始学习java时可能对这2个接口存在一定的疑惑,对于Comparable意思是说:可以与此对象进行比较的那些对象的类型, 此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然...

strict_nerd
2015/05/22
1K
0
重新认识TreeMap

特点 类不仅实现了接口,还实现了接口的子接口。由类实现的集合,不允许键对象为。 核心 1. 红黑树2. 比较器实现大小比较。 红黑树 一种平衡二叉树的实现。 比较器 由于需要排序,所以需要一个...

hgfgoodcreate
2016/03/09
152
0

没有更多内容

加载失败,请刷新页面

加载更多

实战项目-学成在线(一)

之前看的黑马程序员实战项目之一,打算以博客的形式写出来,也让自己重新温习一下。 1、项目背景 略(就是当前这东西很火,我们重点在开发,这些就略过) 2、功能模块 门户,学习中心,教学管...

lianbang_W
18分钟前
1
0
基于Vue的数字输入框组件开发

本文转载于:专业的前端网站➫基于Vue的数字输入框组件开发 1、概述 Vue组件开发的API:props、events和slots 2、组件代码 github地址:https://github.com/MengFangui/VueInputNumber 效果:...

前端老手
26分钟前
2
0
百度地图根据经纬度获取运动轨迹

<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=n......

泉天下
28分钟前
4
0
学习记录(day04-axios增删改查、v-for循环、页面加载成功处理函数)

[TOC] 1.1 基本语法:插值表达式 <template> <div> {{username}} <br/> {{1+2+3}} <br/> {{'你的名字是:' + username}} <br/> {{'abc'.split('')}} </div><......

庭前云落
今天
3
0
CentOS Linux 7上将ISO映像文件写成可启动U盘

如今,电脑基本上都支持U盘启动,所以,可以将ISO文件写到U盘上,用来启动并安装操作系统。 我想将一个CentOS Linux 7的ISO映像文件写到U盘上,在CentOS Linux 7操作系统上,执行如下命令: ...

大别阿郎
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部