Comparable与Comparator,java中的排序与比较
1:比较和排序的概念
比较:两个实体类之间按>,=,<进行比较。
排序:在集合类中,对集合类中的实体进行排序。排序基于的算法基于实体类提供的比较函数。
基本型别都提供了默认的比较算法,如string提供了按字母进行比较,int提供了按整数大小进行比较。
2:Comparable与Comparator
but,在软件开发的世界中,任何没有代码的堆概念都是耍流氓。所以,无论我们解释的多么完美,必须show me the code;
我们首先看这样一段代码:
public class CollectorTest {
public static void main(String[] args) {ArrayList<Student> students = new ArrayList<>();
students.add(new Student("a", 3));
students.add(new Student("c", 2));
students.add(new Student("b", 1));
students.add(new Student("d", 4));
for (Student student : students) {
System.out.printf("name:%s, age: %d \n", student.name, student.age);
}
}
}class Student {
public String name;
public int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
}
但是现在我们需要按年龄大小进行遍历,怎么办?这个时候排序接口就发挥作用了。可以为Student提供排序的接口Comparable,如下,
public class CollectorTest {
public static void main(String[] args) {ArrayList<Student> students = new ArrayList<>();
students.add(new Student("a", 3));
students.add(new Student("c", 2));
students.add(new Student("b", 1));
students.add(new Student("d", 4));
Collections.sort(students);
for (Student student : students) {
System.out.printf("name:%s, age: %d \n", student.name, student.age);
}
}
}class Student implements Comparable{
public String name;
public int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}@Override
public int compareTo(Object o) {
Student student = (Student)o;
if (age> student.age)
{
return 1;
}
else if (age == student.age)
{
return 0;
}
else
{
return -1;
}
//return Integer.valueOf(age).compareTo(Integer.valueOf(student.age));
}
}
输出的结果为:
name:b, age: 1
name:c, age: 2
name:a, age: 3
name:d, age: 4
很棒。PS:注意排序方法中最后被注释掉的一行,排序方法中的逻辑可以被这一行代替,只不过为了给大家演示期间,我还原了这个Integer的compareTo方法。
现在问题来了,我不想用年龄进行排序了,我想用姓名进行排序,该怎么办?要知道我们只能实现一个排序接口,排序接口只有一个方法。这个时候,比较器就派上用场了!
我们实现一个name的比较器,如下:
public class CollectorTest {
public static void main(String[] args) {ArrayList<Student> students = new ArrayList<>();
students.add(new Student("a", 3));
students.add(new Student("c", 2));
students.add(new Student("b", 1));
students.add(new Student("d", 4));
//Collections.sort(students);
students.sort(new NameSorter());
for (Student student : students) {
System.out.printf("name:%s, age: %d \n", student.name, student.age);
}
}
}class Student implements Comparable{
public String name;
public int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}@Override
public int compareTo(Object o) {
Student student = (Student)o;
if (age> student.age)
{
return 1;
}
else if (age == student.age)
{
return 0;
}
else
{
return -1;
}
//return Integer.valueOf(age).compareTo(Integer.valueOf(student.age));
}
}class NameSorter implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Student s1 =(Student) o1;
Student s2 =(Student) o2;
return s1.name.compareTo(s2.name);
}
}
现在的结果:
name:a, age: 3
name:b, age: 1
name:c, age: 2
name:d, age: 4
将来我们要按照性别,按照学生成绩排序,可能还会有更多更多的排序的要求,那就去实现更多的比较器就行了。
3:Comparable与Comparator的泛型版本Comparable<T>与Comparator<T>
如果我们稍有经验,我们就会发现上面的代码的接口Comparable与Comparator都是已经不建议使用了。当泛型出来后,所有非泛型集合类和接口都已经建议尽量不使用了。至于原因,从上面的代码中我们也可以看出一点端倪。
注意查看compare函数,如:
Student s1 =(Student) o1;
Student s2 =(Student) o2;
我们发现这个函数进行了装箱和拆箱。而这是会影响性能的。如果我们的集合中有成千上万个复杂的实体对象,则在排序的时候所耗费掉的性能就是客观的。而泛型的出现,就可以避免掉拆箱和装箱。
故,我们就该实现Comparable<T>与Comparator<T>。最终的代码如下:
package com.zuikc.se.collectors;
/**
* 排序和比较器的用法,Comparable与Comparator,java中的排序与比较
* author:最课程(zuikc.com)
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;public class CollectorTest {
public static void main(String[] args) {ArrayList<Student> students = new ArrayList<>();
students.add(new Student("a", 3));
students.add(new Student("c", 2));
students.add(new Student("b", 1));
students.add(new Student("d", 4));
//Collections.sort(students);
students.sort(new NameSorter());
for (Student student : students) {
System.out.printf("name:%s, age: %d \n", student.name, student.age);
}
}
}class Student implements Comparable<Student>{
public String name;
public int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}@Override
public int compareTo(Student student) {
if (age> student.age)
{
return 1;
}
else if (age == student.age)
{
return 0;
}
else
{
return -1;
}
//return Integer.valueOf(age).compareTo(Integer.valueOf(student.age));
}
}class NameSorter implements Comparator<Student>{
@Override
public int compare(Student s1, Student s2) {
return s1.name.compareTo(s2.name);
}
}
Comparable与Comparator,java中的排序与比较的更多相关文章
- Java中的排序算法(2)
Java中的排序算法(2) * 快速排序 * 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists). * 步骤为: * 1. 从数 ...
- Java中List排序的3种方法
在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作.比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进 ...
- [个人原创]关于java中对象排序的一些探讨(一)
有的时候我们需要将自己定义的对象,有序输出.因为一般我们程序的中间结果需要存储在容器里,那么怎样对容器中的对象按照一定次序输出就是程序员经常需要考虑的问题.本片文章探讨了怎样有序化输出容器中的对象的问 ...
- Java中中文排序器
在Java中使用Collator类按照汉字拼音排序字符串 public static void main(String[] args) throws Exception{ String[] strs ...
- java中的排序--排序容器_TreeSet与TreeMap
1.TreeSet:数据元素可以排序且不可重复. 对比: (1)Set接口:HashSet,元素必须重写hashcode和equals方法. (2)TreeSet:只要可以排序即可.去重:比较等于0即 ...
- java中的排序(自定义数据排序)--使用Collections的sort方法
排序:将一组数据按相应的规则 排列 顺序 1.规则: 基本数据类型:日常的大小排序. 引用类型: 内置引用类型(String,Integer..),内部已经指定规则,直接使用即可.---- ...
- JAVA中List 排序
第一种方法,就是list中对象实现Comparable接口,代码如下: public class SortEntity implements Comparable<SortEntity>{ ...
- [个人原创]关于java中对象排序的一些探讨(三)
这篇文章由十八子将原创,转载请注明,并标明博客地址:http://www.cnblogs.com/shibazijiang/ 对对象排序也可以使用Guava中的Ordering类. 构造Orderin ...
- java中的排序
排序是数据结构中重要的一个部分,也是在实际开发中最易遇到的问题之一,当然了,你也可以不考虑这些排序的算法,直接把要排序的数据insert到数据库中,用数据库的order by再select一下,也能产 ...
随机推荐
- 使用flask开发网站后端
Flask 是一个用于 Python 的微型网络开发框架,可以用于快速的搭建一个小型的网站. 我的搜索引擎:http://www.abelkhan.com 就是基于flask开发 一个flask的He ...
- Swift 路由机制设计
设计模式 APP设计模式多种多样,从最初的MVC到MVVM,再到MVP,VIPER等.越来越多的设计模式被开发出来并得以应用,但不论我们用到哪种设计模式,只需要记住高内聚.低耦合那边是好的设计模式.在 ...
- asp.net core 中灵活的配置方式
asp.net core支持外部文件和命令行参数方式来配置系统运行所需要的配置信息,我们从下面两个常用场景来具体说下具体使用方法. 一.监听地址及端口配置 1,命令行方式 asp.net core系统 ...
- VBS自动按键大全,vbs基本和特殊按键
CreateObject("Wscript.Shell") SendKeys [String] 脚本实现自动按键盘的某个键 过程是:按下F5间隔50毫秒松开F5间隔3000毫秒按下 ...
- CSS3学习系列之背景相关样式(二)
在border-radius属性中指定两个半径 在border-radius属性中,可以指定两个半径,指定方法如下所示: border-radius:40px 20px; 针对这种情况,各种浏览器的处 ...
- Ionic 应用图标,信息修改
Ionic 应用图标,信息修改 Ionic 应用图标 修改 准备好替换的图标并生成各个尺寸的图标 1.使用命令行进入项目根目录,执行命令ionic resources 替换的图片放在resources ...
- 基于Metronic的Bootstrap开发框架经验总结(15)-- 更新使用Metronic 4.75版本
在基于Metronic的Bootstrap开发框架中,一直都希望整合较新.较好的前端技术,结合MVC的后端技术进行项目的开发,随着时间的推移,目前Metronic也更新到了4.75版本,因此着手对这个 ...
- Sass控制命令及函数知识整理
2017-07-07 20:17:17 最底部附结构图(实在是结构图太长了没办法) 2017-06-22 09:11:43 一.Sass的控制命令 1.@if语句 @if 指令是一个 SassSc ...
- [图形学] 计算机图形学 with OpenGL开篇
<计算机图形学>(第四版)正在学习中,学习目的是为了在Unity中使用shader实现不同的渲染效果. 希望在这里能把学习过程中学到的知识和遇到的问题记录下来. 工作环境是:Xcode 8 ...
- vim中常用基本命令
一般模式可用命令,含光标移动.复制粘贴.查找替换等功能 Ctrl+f:屏幕向下移动一页,相当Page Down按钮 Ctrl+b:屏幕向上移动一页,相当Page Up按钮 0或Home键:移动到行首 ...