JAVA中compareTo方法的使用小结

 更新时间:2024年07月09日 09:47:30   作者:天上掉下来个程小白  
compareTo方法的目的是用来比较两个对象的大小的,本文主要介绍了JAVA中compareTo方法的使用小结,具有一定的参考价值,感兴趣的可以了解一下

一、compareTo()方法

在深挖compareTo方法前,首先我们需要了解compareTo方法的来龙去脉。compareTo方法的目的是用来比较两个对象的大小的。假如有两个对象a1,a2。包含姓名,年龄,身高三个属性,现在要求根据年龄或者性别进行排序。这就要用到compareTo方法。

二、如何使用compareTo方法

要想使用compareTo方法对对象进行排序,首先要使得该对象类实现comparable接口,并重写compareTo方法,重写compareTo方法时要制定比较规则。

package com.njau.d6_map_impl;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    private double height;

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Double.compare(height, student.height) == 0 && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, height);   // 没有重写hashCode之前,不同对象不一样。重写后根据属性计算hash值,属性相同的被认为是同一对象,hash值一样。属性是否一样通过重写的equals方法判断
    }

    public Student() {
    }

    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

三、如何指定比较规则

那么该如何指定比较规则呢?这里主要针对int类型数据比较,double类型数据比较以及字符串类型数据比较三种来讲解比较规则:

1.int类型数据比较

int类型的数据指定比较规则最为简单,在重写compareTo方法时,this代表主调对象(主动比较对象),而o代表从调对象(被动比较对象)。Java会默认左边对象是主调对象(this对象),右边对象是从调对象(o对象),这个默认规则是不会改变的。

而比较规则是:当左边对象>右边对象的值时,compareTo方法会返回一个正整数。Java便认为是this对象>o对象(因为Java会默认左边对象就是this,右边对象就是o)。Java排序o,this。

当左边对象<右边对象的值时,compareTo方法会返回一个负整数。Java便认为是this对象<o对象(因为Java会默认左边对象就是this,右边对象就是o)。Java排序this,o。

当左边对象=右边对象的值时,compareTo方法会返回一个负整数。Java便认为是this对象=o对象(因为Java会默认左边对象就是this,右边对象就是o)。

举例说明

package com.njau.d6_map_impl;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    private double height;

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Double.compare(height, student.height) == 0 && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, height);   // 没有重写hashCode之前,不同对象不一样。重写后根据属性计算hash值,属性相同的被认为是同一对象,hash值一样。属性是否一样通过重写的equals方法判断
    }

    public Student() {
    }

    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

假设this.age>o.age

this.age-o.age。左边this右边o,>0则Java则认为左边对象this>右边对象o,则排序为o,this。升序排序。实际上也是升序排序。 

如果想要降序排序,那么则改为o.age-this.age。左边o右边this,<0则Java则认为左边对象this<右边对象o,则排序为this,o。Java认为是升序排序。实际上是降序排序。

2.double类型数据比较

double类型的数据比较,会出现精度问题,因此不能直接相减。为了解决精度问题,Java中的Double.compare方法派上用场。Double.compare(double1,double2),如果double1>double2,则返回正整数。如果double1<double2,则返回负整数。如果double1=double2,则返回0。这样的话,就符合了Java的比较规则。

return Double.compare(o1.getHeight(),o2.getHeight());

3.字符串类型的数据比较

return this.name.compareTo(o.name);

字符串类型的属性进行比较时,会将字符串转换成字符数组,再通过字符数组进行比较,排序时按照字符的Unicode编码进行排序。首先Java虚拟机会将主调字符串(由编译时生成,也叫做value[])赋给String类中定义的value[]字符数组(使用final定义,只能初始化一次)。

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    // The value is used for character storage.
    private final char value[];

    // Other fields and methods...

    // Constructor to initialize string from character array
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

    // Other constructors and methods...
}

紧接着会执行String类中的compareTo方法,将从调字符串进行传入并比较

public int compareTo(String anotherString) {
    int len1 = this.length();
    int len2 = anotherString.length();
    int lim = Math.min(len1, len2);
    char v1[] = this.value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}

this:主调字符串

anotherString:从调字符串(在编译阶段会被转换成字符数组)

原理:

获取字符串长度: 

int len1 = this.length();
int len2 = anotherString.length();

length() 方法返回字符串的长度 

将字符串转换为字符数组:

char v1[] = this.toCharArray();
char v2[] = anotherString.toCharArray();

toCharArray() 方法将字符串转换为字符数组。

逐字符比较:

int k = 0;
while (k < lim) {
    char c1 = v1[k];
    char c2 = v2[k];
    if (c1 != c2) {
        return c1 - c2;
    }
    k++;
}

逐字符比较两个字符串,返回第一个不同字符的差值。 

长度比较: 

return len1 - len2;

如果所有字符都相同,则返回字符串长度的差值。

最终会根据Unicode编码比较出字符串的前后顺序。

到此这篇关于JAVA中compareTo方法的使用小结的文章就介绍到这了,更多相关JAVA compareTo内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现多个wav文件合成一个的方法示例

    Java实现多个wav文件合成一个的方法示例

    这篇文章主要介绍了Java实现多个wav文件合成一个的方法,涉及java文件流读写、编码转换、解析等相关操作技巧,需要的朋友可以参考下
    2019-05-05
  • Java日常练习题,每天进步一点点(13)

    Java日常练习题,每天进步一点点(13)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-07-07
  • 浅谈java异常处理之空指针异常

    浅谈java异常处理之空指针异常

    下面小编就为大家带来一篇浅谈java异常处理之空指针异常。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • SpringBoot整合iText7导出PDF及性能优化方式

    SpringBoot整合iText7导出PDF及性能优化方式

    在SpringBoot项目中整合iText7库以导出PDF文件,不仅能够满足报告生成需求,而且可以处理复杂的文档布局与样式,整合步骤包括添加Maven依赖、编写PDF生成代码,性能优化方面,建议使用流式处理、缓存样式与字体、优化HTML/CSS结构、采用异步处理
    2024-09-09
  • Java中FilterInputStream和FilterOutputStream的用法详解

    Java中FilterInputStream和FilterOutputStream的用法详解

    这篇文章主要介绍了Java中FilterInputStream和FilterOutputStream的用法详解,这两个类分别用于封装输入和输出流,需要的朋友可以参考下
    2016-06-06
  • JPA默认值设置没有效果的解决

    JPA默认值设置没有效果的解决

    这篇文章主要介绍了JPA默认值设置没有效果的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • JAVA中HTTP基本认证(Basic Authentication)实现

    JAVA中HTTP基本认证(Basic Authentication)实现

    HTTP 基本认证是一种简单的认证方法,本文主要介绍了JAVA中HTTP基本认证(Basic Authentication),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • JAVA 中实现整句汉字拆分、转换为ASCII实例详解

    JAVA 中实现整句汉字拆分、转换为ASCII实例详解

    这篇文章主要介绍了JAVA 中实现整句汉字拆分、转换为ASCII实例详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • IntelliJ IDEA基于SpringBoot如何搭建SSM开发环境的步骤详解

    IntelliJ IDEA基于SpringBoot如何搭建SSM开发环境的步骤详解

    这篇文章主要介绍了IntelliJ IDEA基于SpringBoot如何搭建SSM开发环境,本文分步骤通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • springboot 使用mybatis查询的示例代码

    springboot 使用mybatis查询的示例代码

    这篇文章主要介绍了springboot 使用mybatis查询功能,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08

最新评论