Java 实现使用Comparable按照我们指定的规则排序

练习:

存储学生对象并遍历,创建TreeSet集合使用无参构造方法,并按照年龄从小到大的顺序排序,若年龄相同再按照姓名的字母顺序排序

分析:

  • 1.创建学生类,成员变量name,age;无参构造,带参构造;get\set方法;
  • 2.创建测试类,添加数据并进行排序;直接排序会报错
  • 3.需要Student实现comparable接口并重写Comparable中的compareto方法来实现按照我们给定的顺序排序

Student类代码:

public class Student{
    //成员变量
    private String name;
    private int age;
    //构造方法
    public Student(){}
    public Student(String name,int age){
        this.age=age;
        this.name=name;
    }
    //get\set方法
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
}

测试类:

public class StudentDemo {
    public static void main(String[] args) {
        //创建TreeSet对象
        TreeSet<Student>ts=new TreeSet<Student>();
        //创建学生对象
        Student s=new Student("张三",18);
        Student s1=new Student("张四",17);
        Student s2=new Student("张五",19);
        Student s3=new Student("张六",12);
        //添加数据
        ts.add(s);
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        //遍历
        for (Student ss:ts){
           System.out.println(ss.getName()+ss.getAge());
        }
    }
​
}
​

第一次运行结果提示Student cannot be cast to java.lang.Comparable,这个时候我们就需要在Student类实现comparable接口重写compareto方法,并给定返回值

public class Student implements Comparable<Student>{
    //成员变量
    private String name;
    private int age;
    //构造方法
    public Student(){}
    public Student(String name,int age){
        this.age=age;
        this.name=name;
    }
    //get\set方法
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public int compareTo(Student o) {
   //      return 0;
   //      return 1;
   //      return-1;
    }
}

那么可以看到compareto方法中有三个返回值分别是0、1、-1三种情况;

  • 1.return 0:返回值是0的情况下再遍历集合只会在控制台打印出第一个元素;这是因为存入第一个元素时不需要比较直接存入集合,第二个 元素再存入是就需要跟第一个元素比较,但返回值为0,就会认为第二个元素跟第一个元素是相同的、重复的,就不存储,依此类推
  • 2.return 1:返回值是1的情况下再遍历集合会按照存储数据的顺序在控制台全部打印出来;同样的,第一个元素存入不比较,第二个元素与第一个元素比较,返回值为1;就会认为第二个元素比第一个元素大,排在第一个元素后面,以此类推
  • 3.return -1:与renturn 1的情况相反,也就是会按照存储数据顺序的倒序方式在控制台打印出来

思考:我们需要按照年龄的大小排序,这本质上不是只要返回值是一个正数就行了嘛,那我们就可以在compareto方法中这样写

public int compareTo(Student s) {
        //return 0;
        //return 1;
        int num=this.age-s.age;
        return num;
    }

其中,this是方法内部就有的,在这里this.age代表当第一个元素存储后的后续每一个元素的年龄,我们用后续存储的元素年龄减去第一个元素的年龄当结果是-1时,就将该元素排在第一个元素前面,为1时,就排在后面,为0时就代表重复不存储

但是在我们完成按照年龄进行排序后有出现一个问题:当两个元素姓名不同年龄相同时,再按照我们设定的规则就不会将年龄相同的最后一个元素存储进去,因为它们两个年龄相减为0,默认重复了。所以在年龄相同的情况下,我们还要再比较姓名,

如下:

public int compareTo(Student s) {
        //return 0;
        //return 1;
        int num=this.age-s.age;
        int num1=num==0?this.name.compareTo(s.name):num;
        return num1;
​
    }

当年龄不同时返回的还是之前num的值,当年龄相同时比较姓名是否相同不相同返回1代表可以进行存储,相同返回0代表重复。

在这里因为string 本身就实现了comparable接口,所以可以直接调用compareto方法,这样就很好的解决了问题又保证了数据的唯一性

总结:

  • 1.TreeSet集合存储自定义对象时,无参构造方法使用的是自然排序也就是按照存储元素的顺序进行排序
  • 2.自然排序也就是让元素所属的类实现Comparable接口,重写compareto(T o)方法
  • 3.重写compareto(T o)方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

比较器排序Comparator

练习:

存储学生对象并遍历,创建TreeSet集合使用带参构造方法,并按照年龄从小到大的顺序排序,若年龄相同再按照姓名的字母顺序排序

分析:较于comparable来说,comparator无需在Student类中实现comparable接口,可以直接在创建TreeSet集合对象时使用内部类的方式进行

public class StudentDemo {
    public static void main(String[] args) {
        //创建TreeSet对象
        TreeSet<Student>ts=new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
               int num =s1.getAge()-s2.getAge();
               int num1=num==0?s1.getName().compareTo(s2.getName()):num;
               return  num1;
            }
        });
        //创建学生对象
        Student s=new Student("张三",18);
        Student s1=new Student("张四",17);
        Student s2=new Student("张五",19);
        Student s3=new Student("张六",12);
        Student s4=new Student("张七",12);
        //添加数据
        ts.add(s);
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        for (Student ss:ts){
            System.out.println(ss.getName()+ss.getAge());
        }
    }
​
}
​

其中需要注意的是,compare方法传递了两个参数,s1就等同于compareto中的this,但由于内部类无法直接访问Student类的私有成员变量,只能通过get方式来获取,效果等同于自然排序Comparable

感谢1楼前辈给出的指导,文中出现的错误与更正如下:

1.TreeSet集合存储自定义对象时,无参构造方法使用的是自然排序也就是按照存储元素的顺序进行排序) 正确的总结:使用TreeSet时,要么实现Comparable接口,要么指定Comparator,两者并存时优先使用Comparator。否则add方法报错cannot be cast to java.lang.Comparable

可以在TreeMap中找到源码:

/**
 * Compares two keys using the correct comparison method for this TreeMap.
 */
@SuppressWarnings("unchecked")
final int compare(Object k1, Object k2) {
    return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
        : comparator.compare((K)k1, (K)k2);
}
// Student未实现Comparable接口时,初始化TreeSet时,需指定Comparator
TreeSet<Student> ts2 = new TreeSet<>(Comparator.comparingInt(Student::getAge).thenComparing(Student::getName));
ts.add(new Student("张三", 18));

到此这篇关于Java 如何使用Comparable按照我们指定的规则排序的文章就介绍到这了,更多相关Java使用Comparable指定排序内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java 实现Comparable接口排序,升序、降序、倒叙

    本人由于项目开发中需要对查询结果list进行排序,这里根据的是每一个对象中的创建时间降序排序.本人讲解不深,只实现目的,如需理解原理还需查阅更深的资料. 1.实现的效果 2.创建排序的对象 package com.practice.test.comparable; import java.util.Date; /** * 描述:要比较的对象 * * @author cui * @create 2018-12-18 14:07 */ public class MySortBean implemen

  • Java自然排序Comparable使用方法解析

    首先说明用TreeSet集合存储自定义时,无参构造方法使用的是自然排序对元素进行排序的 然后,使用自然排序的前提是,让元素所属的类实现Comparable接口并重写comparaTo(T o)方法,来完成. 其次要注意,重写方法时,一定要注意排序规则必须按照要求的主要条件和条件来写. 下面通过一个需求来具体实现一下. 需求:存储学生对象并遍历,创建TreeSet集合使用无参构造方法. 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序 分析可知,需要两个类:一个学生类(Student

  • Java使用Comparable解决排序问题

    本文实例讲述了Java使用Comparable解决排序问题的方法.分享给大家供大家参考.具体实现方法如下: 一次举重竞赛的比赛规则是:选手的成绩以成功举起的总重量来排序,举起总重量多的排在前面:当举起总重量相同时,按照体重来排序,体重轻的排在前面:要求程序读取数据文件作为输入,并按照上述规则排序后,打印出选手编号:数据文件说明如下:现有5名选手,其选手编号.成功举起的总重量及其体重如数据文件data4.txt,样例内容为: <p> <no>1</no> <lw&g

  • 对比Java中的Comparable排序接口和Comparator比较器接口

    Comparable Comparable 是排序接口. 若一个类实现了Comparable接口,就意味着"该类支持排序". 即然实现Comparable接口的类支持排序,假设现在存在"实现Comparable接口的类的对象的List列表(或数组)",则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序. 此外,"实现Comparable接口的类的对象"可以用作"有序映射(如Tree

  • java中实现Comparable接口实现自定义排序的示例

    实例如下所示: class Student implements Comparable{ String name; int gpa; @Override public int compareTo(Object arg0) { // TODO Auto-generated method stub Student s = (Student)arg0; if(gpa == s.gpa) return name.compareTo(s.name); else if(gpa < s.gpa) return

  • java中元素排序Comparable和Comparator的区别

    目录 Comparable Comparator 总结 初次碰到这个问题是之前有一次电话面试,问了一个小时的问题,其中有一个问题就问到Comparable和Comparator的区别,当时没答出 来.之后是公司入职时候做的一套Java编程题,里面用JUnit跑用例的时候也用到了Comparator接口,再加上JDK的大量的类包括常见的 String.Byte.Char.Date等都实现了Comparable接口,因此要学习一下这两个类的区别以及用法. Comparable Comparable可

  • Java 实现使用Comparable按照我们指定的规则排序

    练习: 存储学生对象并遍历,创建TreeSet集合使用无参构造方法,并按照年龄从小到大的顺序排序,若年龄相同再按照姓名的字母顺序排序 分析: 1.创建学生类,成员变量name,age;无参构造,带参构造:get\set方法: 2.创建测试类,添加数据并进行排序;直接排序会报错 3.需要Student实现comparable接口并重写Comparable中的compareto方法来实现按照我们给定的顺序排序 Student类代码: public class Student{   //成员变量  

  • Java Struts图片上传至指定文件夹并显示图片功能

    继上一次利用Servlet实现图片上传,这次利用基于MVC的Struts框架,封装了Servlet并简化了JSP页面跳转. JSP上传页面 上传一定要为form加上enctype="multipart/form-data",表示提交的数据时二进制的 并且必须是method="post" <%@ page language="java" contentType="text/html; charset=utf-8" page

  • java日期操作工具类(获取指定日期、日期转换、相隔天数)

    本文实例为大家分享了java日期操作工具类,获取指定日期前一天.后一天:日期转换:两个日期之间相隔天数等工具类,供大家参考,具体内容如下 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; public class

  • java中删除 数组中的指定元素方法

    java中删除 数组中的指定元素要如何来实现呢,如果各位对于这个算法不是很清楚可以和小编一起来看一篇关于java中删除 数组中的指定元素的例子. java的api中,并没有提供删除数组中元素的方法.虽然数组是一个对象,不过并没有提供add().remove()或查找元素的方法.这就是为什么类似ArrayList和HashSet受欢迎的原因. 不过,我们要感谢Apache Commons Utils,我们可以使用这个库的ArrayUtils类来轻易的删除数组中的元素.不过有一点需要注意,数组是在大

  • Java 比较接口comparable与comparator区别解析

    这篇文章主要介绍了Java 比较接口comparable与comparator区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package test0; import java.util.Comparator; //限定修饰符为friend不能为public,一个java文件中只能有一个public类 /*** * java程序是从一个public类的main函数开始执行的, *(其实是main线程),就像c程序是从main()函数开

  • JAVA中数组插入与删除指定元素的实例代码

    今天学了Java的数组,写了数组的插入和删除,本人小白,写给不会的小白看,大神请忽略,有错请大家指出来: /** 给数组指定位置数组的插入 */ import java.util.*; public class ArrayInsert{ public static void main(String []args){ System.out.println("请用键盘输入5个数:"); int [] array =new int[10]; Scanner sc=new Scanner(Sy

  • java 查找替换pdf中的指定文本

    本文介绍通过Java程序批量替换PDF中的指定文本内容. 程序环境准备如下: 程序使用环境如图,需要注意的是,本文使用了免费版的PDF jar工具:另外JDK版本建议使用高版本更佳. jar文件导入后,可调用Spire.PDF提供的接口.方法等操作PDF,参考如下导入结果: 注:可手动下载jar包.下载后,解压文件,将lib文件夹下的Spire.Pdf.jar文件导入Java程序. Java 代码示例 import com.spire.pdf.*; import com.spire.pdf.ge

  • Java如何通过File类方法删除指定文件夹中的全部文件

    前言 对delete的解说 那么问题来了!!! (②中的问题,怎么删除文件夹里所有文件,想必很多同学也和我一样懵,) 别着急(往下看) 要用到的方法 (递归思想) 如果文件夹里面还有文件夹,就继续往下找(可能不太官方,个人理解) 接下来 代码展示 方法一: package com.study; import java.io.File; import java.io.IOException; /** 1. 应用场景 2. delete删除只能删除空文件夹 和文件 3. 删除指定文件夹 */ pub

随机推荐