[转载] 比较器(Comparable和Comparator)、自然排序、定制排序
参考链接: Java比较器接口与示例
写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字。我热爱技术、热爱开源、热爱编程。技术是开源的、知识是共享的。 这博客是对自己学习的一点点总结及记录,如果您对 Java、算法 感兴趣,可以关注我的动态,我们一起学习。 用知识改变命运,让我们的家人过上更好的生活。
比如Integer,double等基本类型数据,Java可以对他们进行比较排序,但是在 Java 中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题 。
目录
一、java中的sort()方法二、自然排序:Comparable1.自然排序的定义2.实现过程3.示例代码
三、定制排序 :Comparator1.实现过程2.示例代码
一、java中的sort()方法
在java.util.Collections类中有个sort()方法,主要是用来给数组排序
public class CompareTest1 {
@Test
public void test() {
String[] arr = new String[]{"AA", "SS", "FF", "OO", "EE", "HH"};
System.out.println("排序之前: " + Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序之后: " + Arrays.toString(arr));
}
}
代码执行结果:
排序之前: [AA, SS, FF, OO, EE, HH]
排序之后: [AA, EE, FF, HH, OO, SS]
需求:商场有一批水果,对水果的价格进行排序
水果类:
public class Fruit {
private String name;
private double price;
public Fruit() {
}
public Fruit(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
测试类:
public class CompareTest2 {
@Test
public void test() {
Fruit[] arr = new Fruit[5];
arr[0] = new Fruit("apple", 18);
arr[1] = new Fruit("pear", 6);
arr[2] = new Fruit("banana", 14);
arr[3] = new Fruit("watermelon", 26);
arr[4] = new Fruit("tomato", 6);
System.out.println("排序之前: " + Arrays.toString(arr));
// 排序
Arrays.sort(arr);
System.out.println("排序之后: " + Arrays.toString(arr));
}
}
程序将会报错:
java.lang.ClassCastException: xxx.Fruit cannot be cast to java.lang.Comparable
报错原因:类型转换错误。
为了解决这个错误,对象之间的排序将用到比较器。
Java 实现对象排序的方式有两种:
自然排序: java.lang.Comparable
定制排序: java.util.Comparator
二、自然排序:Comparable
1.自然排序的定义
Comparable 接口强行对实现它的每个类的对象进行整体排序
2.实现过程
实现 Comparable接口的类必须实现 compareTo(Object obj) 方法,两个对象通过 compareTo方法的返回值来比较大小 。 ① 如果当前对象 this 大于形参对象 obj 则返回正整数; ② 如果当前对象 this 小于 形参对象 obj则返回 负整数; ③ 如果当前对象 this 等于 形参对象 obj 则返回零 。 实现 Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort 进行自动排序。 实现此接口的对象可以用作有序映射中的键或有序集合中的集合,无需指定比较器
为了解决类型转换错误,在水果类里面实现Comparable接口。
3.示例代码
水果类:
public class Fruit implements Comparable<Fruit> {
private String name;
private double price;
public Fruit() {
}
public Fruit(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
// 水果价格从低到高进行排序,若价格相同则按水果名称从高到低排序
@Override
public int compareTo(Fruit fruit) {
if (this.price > fruit.price) {
return 1;
} else if (this.price < fruit.price) {
return -1;
} else {
// this.name.compareTo(fruit.name) 按名称从低到高,前面加负号,表示相反
return -this.name.compareTo(fruit.name);
}
}
}
注:测试类代码同Test2 代码执行结果:
排序之前: [Fruit{name='apple', price=18.0}, Fruit{name='pear', price=6.0}, Fruit{name='banana', price=14.0}, Fruit{name='watermelon', price=26.0}, Fruit{name='tomato', price=6.0}]
排序之后: [Fruit{name='tomato', price=6.0}, Fruit{name='pear', price=6.0}, Fruit{name='banana', price=14.0}, Fruit{name='apple', price=18.0}, Fruit{name='watermelon', price=26.0}]
三、定制排序 :Comparator
在实际开发中,遇到当元素的类型实现了Comparable 接口,但是它的排序方式不适合当前的操作;或者根本没有实现Comparable 接口,而又不方便修改代码。那么可以考虑使用 Comparator 的对象进行排序。
1.实现过程
定义一个比较器对象; 重写 compare(Object o1,Object o2) 方法,比较 o1 和 o2 的大小: ① 如果方法返回正整数,则表示 o1 大于 o2 ; ② 如果方法返回 0 ,表示相等; ③ 如果方法返回负整数,表示o1 小于 o2 。
可以 将 Comparator 传递给 sort 方法,从而允许在排序顺序上实现精确控制 。
2.示例代码
public class CompareTest3 {
/**
* 按字符从大到小进行排序
*/
@Test
public void test() {
String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "FF", "DD"};
System.out.println("原来的字符串: " + Arrays.toString(arr));
Arrays.sort(arr, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return -o1.compareTo(o2);
}
});
System.out.println("按字符从大到小排序后的字符串: " + Arrays.toString(arr));
}
}
代码执行结果:
原来的字符串: [AA, CC, KK, MM, GG, FF, DD]
按字符从大到小排序后的字符串: [MM, KK, GG, FF, DD, CC, AA]
对水果的价格进行排序
注:水果类同前,节省篇幅,在此不再重复。
public class CompareTest4 {
@Test
public void test() {
Fruit[] arr = new Fruit[5];
arr[0] = new Fruit("apple", 18);
arr[1] = new Fruit("pear", 6);
arr[2] = new Fruit("banana", 14);
arr[3] = new Fruit("watermelon", 26);
arr[4] = new Fruit("watermelon", 6);
System.out.println("排序之前: " + Arrays.toString(arr));
Arrays.sort(arr, new Comparator<Fruit>() {
// 按照水果名称从低到高排序,若名称相同则按照价格从高到低排序
@Override
public int compare(Fruit o1, Fruit o2) {
if (o1.getName().equals(o2.getName())) {
return -Double.compare(o1.getPrice(), o2.getPrice());
} else {
return o1.getName().compareTo(o2.getName());
}
}
});
System.out.println("排序之后: " + Arrays.toString(arr));
}
}
代码执行结果:
排序之前: [Fruit{name='apple', price=18.0}, Fruit{name='pear', price=6.0}, Fruit{name='banana', price=14.0}, Fruit{name='watermelon', price=26.0}, Fruit{name='watermelon', price=6.0}]
排序之后: [Fruit{name='apple', price=18.0}, Fruit{name='banana', price=14.0}, Fruit{name='pear', price=6.0}, Fruit{name='watermelon', price=26.0}, Fruit{name='watermelon', price=6.0}]
当定制排序和自然排序同时存在时,最终的排序结果是按照定制排序进行排序的。
上一篇 聊聊 StringBuffer 与 StringBuilder
[转载] 比较器(Comparable和Comparator)、自然排序、定制排序相关推荐
- Java常用类(3)--Java比较器Comparable、Comparator类
文章目录 自然排序:java.lang.Comparable 定制排序:java.util.Comparator 自然排序:java.lang.Comparable Comparable接口强行对实现 ...
- 比较器——Comparable与Comparator的使用
目录 1.Comparable 2.Comparator比较器 1.Comparable 当我们要比较对象大小,或者是对对象进行排序时,我们就可以使用接口COmparable,重写该接口中的compa ...
- JAVASE的内、外部比较器Comparable和Comparator
1.内部比较器,自定义实体类实现Comparable接口 /*** @author Nyotengu* @date 18/7/26 15:39*/ public class SortTest {/** ...
- 比较器Comparable跟Comparator
在开发过程中如果需要对集合或数组中的一些属性左比较,并且按照一定的顺序排序的话,java的一个比价好的解决办法是用比较器,这里介绍两种 1.Comparable接口 比如在Person中需要对首先对a ...
- Day48(List接口,ArrayList,LinkedList,Vector,Set接口,HashSet,LinkedHashSet,TreeSet,自然排序,定制排序)
Collection子接口之一:List接口 List接口概述 鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组 List集合类中元素有序.且可重复,集合中的每个元素都有其对应的顺 ...
- 浅析 Comparable和 Comparator的区别
简介 Comparable和 Comparator都是java.util包下的两个接口,从字面上看这两个接口都是用来做比较用的,但是jdk里面不可能定义两个功能相同的接口,所以他们肯定有不同的用处. ...
- Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)
1. Iterator迭代器 所有Collection的实现类都实现了iterator方法,该方法返回一个Iterator接口类型的对象,用于实现对集合元素迭代的便利.在java.util包下. 1) ...
- Comparable 和 Comparator 比较器
Comparable :自然排序(自己单独实现) 自然排序的定义 Comparable 接口强行对实现它的每个类的对象进行整体排序 实现过程 实现 Comparable 接口的类必须实现 compar ...
- TreeSet的自然排序和定制排序
只要放在TreeSet中的元素对象,在该对象的类中必须实现Comparable接口,必须覆盖该接口中的compareTo()方法,并在该方法中编写比较规则.(该方法不能自动生成) 自然排序(Compa ...
最新文章
- 清除administrator密码 方法
- linux启动后分区数据变化,求助!我删除了Linux启动分区
- 【开源项目】基于FFmpeg的封装格式转换
- java2019 数据结构算法面试题_2019年JVM最新面试题,必须收藏它
- linux运行tcl脚本语言,Tool Command Language (Tcl)初体验
- 再谈Js定义变量,你不得不踩的那些坑
- Google是如何识别原创文章的,以及外链建设意见
- ATTCK实战系列三(msf域渗透)
- 企业供应链管理架构图
- Windows清理助手ARSWP
- python search group_python笔记52-re正则匹配search(group groups groupdict)
- 郑州等保测评公司有哪些?在哪里?
- 不用编程语言自带函数,你会如何实现计算平方根
- K8S---Downward API
- apicloud mysql_APICloud 微信授权登录
- UI设计中异常状态设计总结
- LPC1768学习笔记
- IE6 PNG 图片问题分析
- uniapp 中 通过经纬度获取地址详情(vue)
- python处理实验数据,Python在热敏电阻测量实验数据处理中的应用
热门文章
- 【NOIP2002】【Luogu1037】产生数(高精乘低精,DFS暴力搜索)
- 嵌入式linux clion,跨平台IDE集成开发环境Clion教程:嵌入式开发
- mysql5.6.19安装图解_mysql5.6.19安装说明
- 2018CCPC网络赛
- dfs-Bit Compression
- c++排序算法之 快速排序
- 2013蓝桥杯C++A:颠倒的价牌(stringstream用法)
- 递归法:走楼梯; 旋转数组的最小数字(递归法和改进二分法)
- UnityShader25:在Unity中实现泛光
- C++结构体,联合体与枚举类