博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Comparable和Comparator的区别
阅读量:7119 次
发布时间:2019-06-28

本文共 11871 字,大约阅读时间需要 39 分钟。

  

  在中,我们明白了:

    看到tree,可以按顺序进行排列,就要想到两个接口。Comparable(集合中元素实现这个接口,元素自身具备可比性),Comparator(比较器,传入容器构造方法中,容器具备可比性)。

那么Comparable和Comparator有什么区别呢?

1.  Comparable---接口(集合中元素实现此接口,元素具有可比性)

  Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较,则依赖compareTo方法的实现,compareTo方法也被称为自然比较方法。如果开发者add进入一个Collection的对象想要Collections的sort方法帮你自动进行排序的话,那么这个对象必须实现Comparable接口。compareTo(Object o)方法的返回值是int,且此方法只有一个参数,返回值有三种情况:

1、返回正整数

2、返回0

3、返回负整数

  可以这么理解:返回1表示当前元素排在与之对比的元素后面,返回-1表示当前元素排在与之对比的元素前面,返回0表示不排序(按其原顺序排列)。(其实并不是1,-1,0;只要是正数负数和0就可以进行区分)。

  元素自身可以理解为基准,而参数上的obj可以理解为与之对比的元素。

 

1.比如我们想比较人的时候按年龄倒序排列

  思路:实现上面接口,如果与之对比的元素年龄比他大,排在他前面(返回负数),否则排在他后面(返回正数)。

例如:

public class Person implements Comparable
{ private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int compareTo(Person o) { if(this.age > o.getAge()){
//返回负数表示比他大的排在他前面 return -1; } if(this.age < o.getAge()){
//返回整数表示比他小的排在他后面 return 1; } return 0; } public Person(int age, String name) { super(); this.age = age; this.name = name; } @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; } }

 

 

测试:

import java.util.ArrayList;import java.util.Collections;import java.util.List;public class Test1 {    public static void main(String[] args) {        List
list = new ArrayList<>(); list.add(new Person(20, "张三")); list.add(new Person(22, "李四")); list.add(new Person(19, "王五")); list.add(new Person(19, "张是")); list.add(new Person(17, "开发")); list.add(new Person(29, "看")); Collections.sort(list); for(Person p : list){ System.out.println(p); } }}

 

 

结果:

Person [age=29, name=看]

Person [age=22, name=李四]
Person [age=20, name=张三]
Person [age=19, name=王五]
Person [age=19, name=张是]
Person [age=17, name=开发]

 

2.按照上面的思路我们写一个按年龄正序排列

修改上面的compareTo方法:

@Override    public int compareTo(Person o) {        if(this.age > o.getAge()){
//返回正数表示比他大的排在他后面 return 10; } if(this.age < o.getAge()){
//返回负数表示比他小的排在他前面 return -1; } return 0; }

 

 

测试代码还是上面代码,查看结果:

Person [age=17, name=开发]

Person [age=19, name=王五]
Person [age=19, name=张是]
Person [age=20, name=张三]
Person [age=22, name=李四]
Person [age=29, name=看]

 

3.将自身具有可比性的元素存入TreeSet或者TreeMap进行查看(TreeSet会自动将元素排序,元素作为key的时候TreeMap会根据key排序)

Person.java

package cn.qlq.test;public class Person implements Comparable
{ private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int compareTo(Person o) { if(this.age > o.getAge()){
//返回负数表示比他大的排在他前面 return -1; } if(this.age < o.getAge()){
//返回整数表示比他小的排在他后面 return 1; } return 0; } public Person(int age, String name) { super(); this.age = age; this.name = name; } @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; } }

 

 

测试代码:

package cn.qlq.test;import java.util.Map;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;public class TreeSetTest {    public static void main(String[] args) {        Set
list = new TreeSet<>(); list.add(new Person(20, "张三")); list.add(new Person(22, "李四")); list.add(new Person(19, "王五")); list.add(new Person(19, "张是")); list.add(new Person(17, "开发")); list.add(new Person(29, "看")); for(Person p : list){ System.out.println(p); } System.out.println("-----------------------------"); //作为key会将key排序 Map map = new TreeMap(); map.put(new Person(20, "张三"), "1"); map.put(new Person(22, "李四"), "2"); map.put(new Person(19, "张三"), "3"); map.put(new Person(25, "哇塞"), "4"); for(Object key :map.keySet()){ System.out.println(key+"\t"+map.get(key)); } System.out.println("-----------------------------"); //作为value无效 Map map2 = new TreeMap(); map2.put("1",new Person(20, "张三")); map2.put("2",new Person(22, "李四")); map2.put("3",new Person(19, "张三")); map2.put("4",new Person(25, "哇塞")); for(Object key :map2.keySet()){ System.out.println(key+"\t"+map2.get(key)); } }}

 

 

结果:

Person [age=29, name=看]

Person [age=22, name=李四]
Person [age=20, name=张三]
Person [age=19, name=王五]
Person [age=17, name=开发]
-----------------------------
Person [age=25, name=哇塞] 4
Person [age=22, name=李四] 2
Person [age=20, name=张三] 1
Person [age=19, name=张三] 3
-----------------------------
1 Person [age=20, name=张三]
2 Person [age=22, name=李四]
3 Person [age=19, name=张三]
4 Person [age=25, name=哇塞]

 

 

 

2.  Comparator---接口(可以理解为比较器,给集合传递比较器集合具有可比性)

  Comparator相当于外部比较器,其作为参数传给具有可比性的集合,使集合具有可比性。比如:      TreeSet ts = new TreeSet(new MyComparator());   比较器需要重写compareTo(Object o1,Object o2)方法,返回值也是下面三个值:

1、返回正整数

2、返回0

3、返回负整数

  可以这么理解:返回1表示当前元素排在与之对比的元素后面,返回-1表示当前元素排在与之对比的元素前面,返回0表示不排序(按其原顺序排列)。(其实并不是1,-1,0;只要是正数负数和0就可以进行区分)

   compareTo(Object o1,Object o2)方法的第一个参数可以理解为基准,而参数上的第二个参数可以理解为与之对比的元素。

1.比如我们想比较人的时候按年龄倒序排列

public class Person{    private int age;    private String name;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Person(int age, String name) {        super();        this.age = age;        this.name = name;    }    @Override    public String toString() {        return "Person [age=" + age + ", name=" + name + "]";    }    }

 

 

比较器类:(可以理解为第一个参数是基准,第二个参数是与之对比的元素,返回-1表示基准排在与之对比元素前面,返回1表示基准在与之对比的元素后面)

import java.util.Comparator;public class PersonComparator implements Comparator
{ /** * 第一个参数可以理解为基准,第二个是与之比较多元素 。返回负数表示排在其前面,返回正数表示排在其后面 */ @Override public int compare(Person o1, Person o2) { if (o1.getAge() > o2.getAge()) {
// 返回正数表示比他大的排在他后面 return -1; } if (o1.getAge() < o2.getAge()) { return 1; } return 0; }}

 

 

测试代码:

import java.util.ArrayList;import java.util.Collections;import java.util.List;public class Test1 {    public static void main(String[] args) {        List
list = new ArrayList<>(); list.add(new Person(20, "张三")); list.add(new Person(22, "李四")); list.add(new Person(19, "王五")); list.add(new Person(19, "张是")); list.add(new Person(17, "开发")); list.add(new Person(29, "看")); Collections.sort(list,new PersonComparator()); for(Person p : list){ System.out.println(p); } }}

 

 

结果:

Person [age=29, name=看]

Person [age=22, name=李四]
Person [age=20, name=张三]
Person [age=19, name=王五]
Person [age=19, name=张是]
Person [age=17, name=开发]

 

 

2.写一个正序的比较器就简单了

import java.util.Comparator;public class PersonComparator implements Comparator
{ /** * 第一个参数可以理解为基准,第二个是与之比较多元素 。返回负数表示排在其前面,返回正数表示排在其后面 */ @Override public int compare(Person o1, Person o2) { if (o1.getAge() > o2.getAge()) { return 10; } if (o1.getAge() < o2.getAge()) { return -10; } return 0; }}

 

3.将一个比较器传入TreeSet或者TreeMap是集合有序,或者TreeMap的key值有序(也就是TreeMap排序是将key排序)

  TreeSet中的元素会自动排序,根据传下来的比较器对里面的元素进行排序。TreeMap传入比较器的话是元素作为key才可以排序,如果传入比较器但是key不是比较器指定的元素会报错。。。。。。。

比较器:

package cn.qlq.test;import java.util.Comparator;public class PersonComparator implements Comparator
{ /** * 第一个参数可以理解为基准,第二个是与之比较多元素 。返回负数表示排在其前面,返回正数表示排在其后面 */ @Override public int compare(Person o1, Person o2) { if (o1.getAge() > o2.getAge()) {
// 返回正数表示比他大的排在他后面 return 10; } if (o1.getAge() < o2.getAge()) { return -10; } return 0; }}

 

 

测试代码:

package cn.qlq.test;import java.util.Map;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;public class TreeSetTest {    public static void main(String[] args) {        Set
list = new TreeSet<>(new PersonComparator()); list.add(new Person(20, "张三")); list.add(new Person(22, "李四")); list.add(new Person(19, "王五")); list.add(new Person(19, "张是")); list.add(new Person(17, "开发")); list.add(new Person(29, "看")); for(Person p : list){ System.out.println(p); } System.out.println("-----------------------------"); //作为key不会报错,会将key排序 Map map = new TreeMap(new PersonComparator()); map.put(new Person(20, "张三"), "1"); map.put(new Person(22, "李四"), "2"); map.put(new Person(19, "张三"), "3"); map.put(new Person(25, "哇塞"), "4"); for(Object key :map.keySet()){ System.out.println(key+"\t"+map.get(key)); } //作为value报错 Map map2 = new TreeMap(new PersonComparator()); map2.put("1",new Person(20, "张三")); map2.put("2",new Person(22, "李四")); map2.put("3",new Person(19, "张三")); map2.put("4",new Person(25, "哇塞")); for(Object key :map2.keySet()){ System.out.println(key+"\t"+map2.get(key)); } }}

 

 

结果:

package cn.qlq.test;import java.util.Map;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;public class TreeSetTest {    public static void main(String[] args) {        Set
list = new TreeSet<>(new PersonComparator()); list.add(new Person(20, "张三")); list.add(new Person(22, "李四")); list.add(new Person(19, "王五")); list.add(new Person(19, "张是")); list.add(new Person(17, "开发")); list.add(new Person(29, "看")); for(Person p : list){ System.out.println(p); } System.out.println("-----------------------------"); //作为key不会报错,会将key排序 Map map = new TreeMap(new PersonComparator()); map.put(new Person(20, "张三"), "1"); map.put(new Person(22, "李四"), "2"); map.put(new Person(19, "张三"), "3"); map.put(new Person(25, "哇塞"), "4"); for(Object key :map.keySet()){ System.out.println(key+"\t"+map.get(key)); } System.out.println("-----------------------------"); //key不是Person实例会报错 Map map2 = new TreeMap(new PersonComparator()); map2.put("1",new Person(20, "张三")); map2.put("2",new Person(22, "李四")); map2.put("3",new Person(19, "张三")); map2.put("4",new Person(25, "哇塞")); for(Object key :map2.keySet()){ System.out.println(key+"\t"+map2.get(key)); } }}

 

 

结果:

Person [age=17, name=开发]

Person [age=19, name=王五]
Person [age=20, name=张三]
Person [age=22, name=李四]
Person [age=29, name=看]
-----------------------------
Person [age=19, name=张三] 3
Person [age=20, name=张三] 1
Person [age=22, name=李四] 2
Person [age=25, name=哇塞] 4
-----------------------------
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to cn.qlq.test.Person
at cn.qlq.test.PersonComparator.compare(PersonComparator.java:1)
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at cn.qlq.test.TreeSetTest.main(TreeSetTest.java:37)

 

转载地址:http://hdiel.baihongyu.com/

你可能感兴趣的文章
最课程学员启示录:一份有诚意的检讨书
查看>>
即时通信(IM)和实时通信(RTC)的区别
查看>>
面试题解:输入一个数A,找到大于A的一个最小数B,且B中不存在连续相等的两个数字...
查看>>
Linux Linux程序练习九
查看>>
Nginx的启动、停止与重启
查看>>
Windows 64 位 mysql 5.7.20 安装教程
查看>>
css点滴3—5种方式实现圆环
查看>>
剑指offer 最小的k个数 leetcode 215. Kth Largest Element in an Array
查看>>
screen 命令使用及示例
查看>>
windows10环境下的RabbitMQ安装步骤(图文)
查看>>
Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二十八):kafka0.10.1 内置性能测试API用法示例...
查看>>
【html+css3】在一张jpg图片上,显示多张透明的png图片
查看>>
WPF 3D模型的一个扩展方法
查看>>
postgreSQL学习(二):pgsql的一些基础操作
查看>>
openstack之镜像管理
查看>>
Gartner 2018 年WAF魔力象限报告:云WAF持续增长,Bot管理与API安全拥有未来
查看>>
如何在Java客户端调用RESTful服务
查看>>
一个月薪两万的Web安全工程师要掌握哪些技能?
查看>>
同事写得Python对页面压测脚本
查看>>
H2:开源内存数据库引擎
查看>>