Comparatable接口和Comparator接口的使用与区别
- 什么是自然排序
- Collections.sort()与Arrays.sort()的异同点
- Comparatable接口和Comparator接口各自的排序依据(理论讲解)
- Comparatable接口和Comparator接口实用排序方法(实际例子分析)
- 综合使用Comparatable和Comparator进行整体排序
- BigDecimal BigInteger Byte Double Float Integer Long Short 类型,是按照数值的大小进行排序的。例如:12<23, 111.111>3.23
- Character及String类型,是按照各个字符的Unicode值大小来排序的。例如:"3BC"<"AB"<"aBC"<"一二"
2、Collections.sort()与Arrays.sort()的异同点
- Collections.sort()://它的定义只有以下两个
public static <T extends Comparable<?
super T>> void sort(List<T> list);
public static <T> void sort(List<T> list, Comparator<? super T> c);
- Arrays.sort()://它的定义有很多,这里列出有代表性的三个
public static void sort(int[] a);
public static void sort(Object[] a);
public static <T> void sort(T[] a, Comparator<?
super T> c);
从它们的定义中,我们可以看出两点:
- 不同点:它们适用对象不一样。
- Collections.sort()仅适用于列表型;
- Arrays.sort()仅适用数组类型,当然数组可以是int、float等,甚至可以是Object对象。
2. 共同点:它们都直接或间接地使用Comparatable接口或Comparator接口。
- Collections.sort()很明显地引用了这两个接口,这里就不细说了;
- Arrays.sort()中,其实,int、float等对应的封装类Integer、Float等class中,都有实现对接口Comparable的引用,例如:Integer的定义如下:
public final class Integer
- extends Number
- implements Comparable<Integer>
- Comparable接口在默认情况下,具有自然排序功能。所以,当我们使用Arrays.sort(int[])时,就已经实现了对int[]进行自然排序的功能了。
3、Comparatable接口和Comparator接口各自的排序依据
既然是排序,那就需要指定排序依据元素,且只要指定了排序依据元素,并且调用的方法得当,那么一定可以成功排序。(请牢牢记住这句话)
- 对于单元素的类,例如:int、float、double、char、String等数据类型,排序依据元素就是它相应的这个单元素。
- 对于多元素的类,例如:我们自定义一个Student类,它的属性有int
age;String name;等,那么我们就需要指定一个排序依据元素。
- 单元素类排序。(一般是指Java中已经实现Comparable接口的类,常用的有:Integer、Float、Double、String、Character等),这些类已经有了排序依据元素,所以可以直接排序。因此,在排序中,我们可以这样做:(以int为例)
int[] intArray = {12,34,0,5,-7,8,1,3};
Arrays.sort(intArray); //这里就是直接依据int值的大小来排序的
for(int i=0;i<intArray.length;i++)
System.out.println(intArray[i]);
程序运行的结果是:(自然排序)
- 多元素类排序。
首先,需要进行排序的这个多元素类(如:Student)必须实现Comparable<T>接口,且T为该多元素类的类名。
例如:public static Student implments Comparable<Student>
然后,在该类中(一定要在该内的内部)实现comparaTo()方法,在这里,我们将指定排序依据元素。
例如:
@Override
public int compareTo(Student arg0) {
return arg0.getName().compareTo(this.name);//这里我们指定name为排序依据元素
}
最后,根据Student实例化时,是用List<Student>、还是Student[]来实现的,选择使用 Collection.sort()或Arrays.sort()进行排序。
与Comparable不同的是,要实现Comparator接口,一定要在程序中指定排序依据元素(不管是单元素,还是多元素)。而且,这个实现Comparator接口的类一定要在排序的类(如Student)之外。可以是匿名类,如:
public int compare(Student one, Student another) {
return one.getAge() - another.getAge();
}
});
也可以是一个外部类,如class StudentSort implments<Student>{};的实例,Collention.sort(allStudent,new StudentSort());
小结:Comparatable接口必须由需要排序的多元素类本身来实现,且在其内部重写comparaTo()方法;Comparator接口是在需要排序的多元素类的外部(即使用外部类)来实现,且必须在该外部类中重写compara()方法。
- 类名:Student
- 属性值:long ID;String name;int age;float score;
- 要求:根据学号、姓名或成绩升序排序所有Student实例
下面两种方法中,橘红色部分为两种方法不同的地方。
一、使用Camparable接口(共2个文件,按学号进行升序排序)
package keNan.com.stu.StudentInfomation;
public class Student implements Comparable<Student>{
private String ID;
private String name;
private int age;
private double score;
//为Student定义两个构造方法
public Student(String ID, String name) {
this(ID,name,0,0);
}
public Student(String ID, String name, int age, double score){
this.ID = ID;
this.name = name;
this.age = age;
this.score = score;
}
//属性值访问与修改
public String getID(){
return ID;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public double getScore(){
return score;
}
public void setID(String newID){
ID = newID;
}
public void setName(String newName){
name = newName;
}
public void setAge(int newAge){
if(newAge < 0)
newAge = 0;
age = newAge;
}
public void setScore(double newScore){
if( (newScore < 0 )||(newScore > 100))
newScore = 0;
score = newScore;
}
//重写对象字符串表示方法
@Override
public String toString() {
String info = new String();
info = ID + '\t' + name + '\t' + age + '\t' + score + '\n';
return info;
}
@Override
public int compareTo(Student arg0) {
return this.ID.compareTo(arg0.ID);//此种写法为升序,若改为arg0.ID.compareTo(this.ID)则为降序
}
}
package keNan.com.stu.StudentInfomation;
import java.util.Arrays;
public class StudentManage{
public static void main(String[] args){
//定义一个学生数据库
final int STUDENT_NUM = 4;
Student[] allStudents = new Student[STUDENT_NUM];
//初始化学生数据库
allStudents[0] = new Student("00001","a");
allStudents[1] = new Student("00003","b");
allStudents[2] = new Student("00002","c");
allStudents[3] = new Student("00004","d");
for(int i=0;i<allStudents.length;i++){
allStudents[i].setAge(i*10);
}
for(int i=0;i<allStudents.length;i++){
allStudents[i].setScore(99 - i*1.5);
}
//按学号升序排序
Arrays.sort(allStudents);
//显示学生信息
System.out.println("学号" + "\t姓名" + "\t年龄" + "\t成绩");
for(int i=0;i<allStudents.length;i++){
System.out.print(allStudents[i]);
}
}
}
程序运行结果:
二、使用Camparator接口(共2个文件,先按姓名升序进行排序,再成绩降序排序)
package keNan.com.stu.StudentInfomation;
public class Student{
private String ID;
private String name;
private int age;
private double score;
//为Student定义两个构造方法
public Student(String ID, String name) {
this(ID,name,0,0);
}
public Student(String ID, String name, int age, double score){
this.ID = ID;
this.name = name;
this.age = age;
this.score = score;
}
//属性值访问与修改
public String getID(){
return ID;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public double getScore(){
return score;
}
public void setID(String newID){
ID = newID;
}
public void setName(String newName){
name = newName;
}
public void setAge(int newAge){
if(newAge < 0)
newAge = 0;
age = newAge;
}
public void setScore(double newScore){
if( (newScore < 0 )||(newScore > 100))
newScore = 0;
score = newScore;
}
//重写对象字符串表示方法
@Override
public String toString() {
String info = new String();
info = ID + '\t' + name + '\t' + age + '\t' + score + '\n';
return info;
}
}
package keNan.com.stu.StudentInfomation;
import java.util.Arrays;
import java.util.Comparator;
public class StudentManage{
public static void main(String[] args){
//定义一个学生数据库
final int STUDENT_NUM = 4;
Student[] allStudents = new Student[STUDENT_NUM];
//初始化学生数据库
allStudents[0] = new Student("00001","a");
allStudents[1] = new Student("00003","b");
allStudents[2] = new Student("00002","c");
allStudents[3] = new Student("00004","d");
for(int i=0;i<allStudents.length;i++){
allStudents[i].setAge(i*10);
}
for(int i=0;i<allStudents.length;i++){
allStudents[i].setScore(99 - i*1.5);
}
//按姓名升序排序
Arrays.sort(allStudents,new ComparatorWithNameUP());
//显示学生信息
System.out.println("学号" + "\t姓名" + "\t年龄" + "\t成绩");
for(int i=0;i<allStudents.length;i++){
System.out.print(allStudents[i]);
}
//按成绩降序排序
Arrays.sort(allStudents,new ComparatorWithScoreDown());
//显示学生信息
System.out.println("学号" + "\t姓名" + "\t年龄" + "\t成绩");
for(int i=0;i<allStudents.length;i++){
System.out.print(allStudents[i]);
}
}
}
//按姓名进行升序排序的外部类,用Comparator接口
class ComparatorWithNameUP implements Comparator<Student>{
@Override
public int compare(Student arg0, Student arg1) {
// TODO Auto-generated method stub
return arg0.getName().compareTo(arg1.getName());
}
}
//按成绩降序
class ComparatorWithScoreDown implements Comparator<Student>{
@Override
public int compare(Student arg0, Student arg1) {
// TODO Auto-generated method stub
if(arg1.getScore() > arg0.getScore())
return 1;
else {
if(arg1.getScore() == arg0.getScore())
return 0;
else return -1;
}
}
}
程序运行结果:
- 优点是,对于单元素集合可以实现直接自然排序;
- 缺点是,对于多元素排序,它的排序依据元素是固定的(compareTo()抽象方法只能实现一次),因此排序方式固定。
Comparator:
- 优点是,元素的排序依据元素是可变的,因为可以定义N多个外部类,每个外部类实现一种排序。在不同需求下,选择不同的排序。
- 缺点是,无论是多元素,还是单元素,都必须自己创建一个外部类来实现排序。
所以在实际运用当中,可以用Comparable的compareTo()方法来定义默认排序方式,用Comparator定义其他排序方式。
还有一点要注意,即使Student类已经implements Comparable<Student>,但是我们在自定义外部类,如class
ComparatorWithNameUP implements Comparator<Student>,并在排序时引用sort(allStudents,new ComparatorWithNameUp());生效的排序算法是ComparatorWithNameUp.
参考资料:
Comparatable接口和Comparator接口的使用与区别的更多相关文章
- java中Comparatable接口和Comparator接口的区别
1.不同类型的排序规则 .自然排序是什么? 自然排序是一种升序排序.对于不同的数据类型,升序规则不一样: BigDecimal BigInteger Byte Double Float Int ...
- 比较器:Compare接口与Comparator接口区别与理解
一.实现Compare接口与Comparator接口的类,都是为了对象实例数组排序的方便,因为可以直接调用 java.util.Arrays.sort(对象数组名称),可以自定义排序规则. 不同之处: ...
- Java中实现对象的比较:Comparable接口和Comparator接口
在实际应用中,我们往往有需要比较两个自定义对象大小的地方.而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的.所以Java中 ...
- Java6.0中Comparable接口与Comparator接口详解
Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...
- Java:实现对象的比较 comparable接口和comparator接口
在实际应用中,我们往往有需要比较两个自定义对象大小的地方.而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的.所以Java中 ...
- Java—集合框架 Collections.sort()、Comparable接口和Comparator接口
Collentions工具类--java.util.Collections Collentions是Java集合框架中,用来操作集合对象的工具类,也是Java集合框架的成员,与List.Map和Set ...
- Comparable接口与Comparator接口的比较————总结
之前的两篇文章主要学习了Comparable接口和Comparator接口的学习.既然已经学习完了,现在就趁热打铁,进行总结吧! Comparable接口和Comparator接口的共同点: 1. 都 ...
- Java中的Comparable接口和Comparator接口
Comparator位于包java.util下,比较器,是在集合外部定义排序.Comparable位于包java.lang下,代表当前对象可比较的,是在集合内部实现排序. Comparable代表一个 ...
- Java之Comparable接口和Comparator接口
Comparable & Comparator 都是用来实现集合中元素的比较.排序的: Comparable 是在集合内部定义的方法实现的排序: Comparator 是在集合外部实现的排序: ...
随机推荐
- 【疯了C#】神奇的换肤(一)
之前看网上有换肤控件IrisSkin2的介绍,感觉很神奇,今天亲自做下试验,C#越来越有趣了,是Labview无法比拟的. 前期准备工作如下:下载后IrisSkin2.dll及匹配的皮肤. 其中ssk ...
- python中sort()方法的cmp参数
<python基础编程>里有讲到一段高级排序: “如果希望元素能按照特定的方式进行排序(而不是sort函数默认的方式,即根据python的默认排序规则按升序排列元素,第5章内对此进行讲解) ...
- python--基本代码规范
python代码规范:一.标识符 所谓的标识符就是对变量.常量.函数.类等对象起的名字 python语言在任何场景都严格区分大小写!!! python对于标识符的命名有如下规定: 第一个字符必须是字母 ...
- @angular/cli项目构建--interceptor
JWTInterceptor import {Injectable} from '@angular/core'; import {HttpEvent, HttpHandler, HttpInterce ...
- 分析 PHP升级导致系统负载过高问题(转载)
原文:http://chuansongme.com/n/797172 背景 据XX部门兄弟反应, 其在将PHP从5.3.8 升级到5.5.13 时, 开始运行正常, 运行一段时间后, 系统负载变高,达 ...
- java web service 上传下载文件
1.新建动态web工程youmeFileServer,新建包com,里面新建类FileProgress package com; import java.io.FileInputStream; imp ...
- Java中print()、printf()、println()的区别?
区别: 1.printf主要是继承了C语言的printf的一些特性,可以进行格式化输出 2.print就是一般的标准输出,输入信息后不会换行 3.println输入信息会换行 参照JAVA API的定 ...
- (C#)把磁盘目录树加载在窗体菜单中
这又是一个没有技术含量的代码.写出来只是玩玩,所以也不敢放在首页. 这里有个问题,是获取文件/文件夹的图标.使用 System.Drawing.Icon.ExtractAssociatedIcon 只 ...
- SSL与TLS的区别
SSL(Secure Socket Layer 安全套接层)是基于HTTPS下的一个协议加密层,最初是由网景公司(Netscape)研发,后被IETF(The Internet Engineering ...
- Android高仿京东淘宝自动无限循环轮播控件的实现思路和过程
在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的实现思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于 ...