Java集合排序方法comparable和comparator的总结

2023-10-27

Java集合排序方法的总结

-----接口comparable和接口comparator的比较

一.相关概念

Comparable和Comparator都是用来实现集合中元素的比较、排序的。
   (一) Comparable

Comparable是在集合内部定义的方法实现的排序,位于java.util下。是一个对象本身就已经支持自比较所需要实现的接口,如String、Integer自己就实现了Comparable接口,可完成比较大小操作。自定义类要在加入list容器中后能够排序,也可以实现Comparable接口,在用Collections类的sort方法排序时若不指定Comparator,那就以自然顺序排序。所谓自然顺序就是实现Comparable接口设定的排序方式。

  (二)Comparator

Comparator是在集合外部实现的排序,位于java.lang下。是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。Comparator体现了一种策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。使用方法只能用Collections类的sort方法,并且是传递两个参数进去(List list,Class class),第一个参数是集合的对象list,第二个是实现了comparator接口的实现类的对象。

 

总而言之Comparable是自已完成比较,Comparator是外部程序实现比较。

 

二.详细示例

(一)comparable详细使用方法

    1. 功能:按照存储的对象的某个属性排列来显示该对象的所有属性

    2. 使用方法:

    使用要注意下,存放TreeSet类的的元素,必须要对泛型实现Comparable接口, 否则运行时add方法就报错,重写compareTo方法就可以排序,而HashSet不支持排序。

    如果要对List的实现类ArrayList和LinkedList里面的对象的元素进行排序就要使用Collections的方法sort(List list),把list的值放进去就可以了

   (1)Comparable是一个接口,需要实现后才能使用, 比如:要对User这个对象的某个属性来排列显示时,Comparable被实现时需要在后面添加泛型如:类名 implements Comparable<User>

   (2)实现接口后要重写方法compareTo(只有一个参数),

   (3)如果比较的的数字,方法返回number-Object.number

   (4)如果比较的的字符串,方法返回string.equal(Object.string)

   (5)正常是按升序排列,在返回前面加个负号就可以降序排列

 3.Comparable的示例

(1)泛型类实现Comparable


package com.xykj.comparable;
public class User implements Comparable
   
   
    
     {//这里的User是后面集合类的泛型
    String name = "";
    String password = "";
    public User(String name, String password) {
       this.name = name;
       this.password = password;
    }
    // 实现排序必须要重写的方法
    @Override
    public int compareTo(User o) {//按照密码的升序排列,想要按照名字排序就把password换成name就可以了
       return password.compareTo(o.password);
    }
    // 重写toString方法
    @Override
    public String toString() {
       return name + "    " + password;
    }
}
   
   

(2)TreeSet类的排序

package com.xykj.comparable;
import java.util.TreeSet;
public class StreeSetTest {
    // TreeSet类的使用,可以对存放的数据进行排序
    public static void main(String[] args) {
       //TreeSet能够排序是因为泛型User类,已经实现了Comparable接口
       TreeSet
   
   
    
     tSet = new TreeSet<>();
       for (int i = 1; i <= 10; i++) {
           //如果泛型User类没有实现Comparable接口,add方法就报错
           tSet.add(new User("TreeSet" + i, "TreeSet" + (50 - i)));
       }
       //Collections.sort(tSet);不能使用,sort里面只能存放List类的对象
       for (User user : tSet) {
           System.out.println(user.toString());//因为重写了toString方法,所以会显示User的名字和密码
       }
    }
}
   
   

 

运行结果:



虽然是按照name的升序添加的,但是结果还是按照password的升序排列



(3)HashSet的演示


package com.xykj.comparable;
import java.util.HashSet;
public class HashSetTest {
    // HashSet类的使用,不支持对元素数据进行排序
    public static void main(String[] args) {
       //即使泛型User类实现了comparable接口,但是结果还是没有排序
       HashSet
   
   
    
     hSet = new HashSet<>();
        for (int i = 1; i <= 10; i++) {
           //即使泛型User类没有实现了comparable接口,add方法也不会报错
           hSet.add(new User("hSet_name" + i, "hSet_password" + (50 - i)));
       }
       for (User user : hSet) {
           System.out.println(user.toString());
       }
    }
}
 
   
   

运行结果:




同样是按照升序进行添加的,但是无论name还是password都没有一点顺序

 

(4)ArrayList的排序,重点理解哦


package com.xykj.comparable;
import java.util.ArrayList;
import java.util.Collections;
public class ArrayListTest {
    //对ArrayList排序必须要使用Collections.sort(list),否则不会排序,
    //会按照添加的顺序打印出来
    public static void main(String[] args) {
       ArrayList
   
   
    
     list = new ArrayList<>();
       for (int i = 1; i <= 10; i++) {
           list.add(new User("ArrayList_name" + i, " ArrayList_password" + (50 - i)));
       }
       //Collections.sort(list);先注释看看结果
       for (User user : list) {
           System.out.println(user.toString());
       }
    }
}
   
   
运行结果:


 


没有使用Collections.sort(list);的情况下怎样的顺序添加的就按照怎样的顺序输出

 

如果使用Collections.sort(list);把注释的代码放出来,还是上面的代码:

 

 

运行的结果就会发生变化:





按照密码的升序排列出来,而不是输入的顺序。

 

 

 

   (5)LInkedList的排序

package com.xykj.comparable;
import java.util.Collections;
import java.util.LinkedList;
public class LinkedListTest {
    //LinkedList的排序
    public static void main(String[] args) {
       LinkedList
   
   
    
     list = new LinkedList<>();
       for (int i = 1; i <= 10; i++) {
           list.add(new User("LinkedList_name" + i, "LinkedList_password" + (50 - i)));
       }
       //使用sort方法排序
       Collections.sort(list);
       for (User user : list) {
           System.out.println(user.toString());
       }
    }
}
   
   


运行结果:




效果和ArrayList是一样的,如果没有使用sort方法也是会按照添加顺序打印出来

 

 

Comparable的总结,使用Comparable可以对TreeSet类的元素进行排序,也可以对ArrayList类和LinkedList类的元素进行排序。

 

对TreeSet类排序的理解,这个和TreeSet的存储方式有关,不排序就不让你存储的意思。

对ArrayList类和LinkedList类排序的理解,这个其实和Arrays类相似,Arrays类有sort方法可以直接传入一个数组名字,

该数组就会被从小到大排序,其实是差不多的意思。这里的Collections类也有一个sort方法,但是只能传递List类型的对象。

 

(一)Comparator详细使用方法

    1. 功能:按照存储的对象的某个属性排列来显示该对象的所有属性,只能对任意集合List接口下的实现类ArrayList和LinkedList进行排序

2.使用方法:

    (1)需要在另一个类是实现Comparator,同样后面也要加泛型,这个泛型是需要排序的自定义类

    (2)要重写compare方法,比较Object里面的具体属性用compareTo

   (3)需要Collections工具类的sort方法,方法里面传入两个参数:第一个参数是列表信息list,第二个参数是实现了comparator的类的对象

    

3.Comparator的示例

(1)先建一个基本属性类


package com.xykj.comparatorTest;
public class Student {
    //创建两个基本属性
    String name="";
    int age=0;
   
    //从写构造方法用来传递数据
    public Student(String name, int age) {
       super();
       this.name = name;
       this.age = age;
    }
    //从写toString方法,方便显示
    @Override
    public String toString() {
       return name + "  " + age ;
    }
   
    //基本属性的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;
    }
   
}

 

 

(2)创建按照姓名升序排列的实现类


package com.xykj.comparatorTest;
 
import java.util.Comparator;
       //按照名字的升序排列    实现接口       泛型是自定义类,里面有要排序的内容   
public class NameSort implements Comparator
   
   
    
    {
    @Override         //两个参数是泛型的对象
    public int compare(Student o1, Student o2) {
                  //按照姓名的升序排列,前面加个负号就按照降序排列
       return o1.getName().compareTo(o2.getName());
    }
}
   
   


 

(3)创建按照年龄升序排列的实现类


package com.xykj.comparatorTest;
import java.util.Comparator;
//按照年龄的升序排列     实现接口          泛型是自定义类,里面有要排序的内容  
public class AgeSort implements Comparator
   
   
    
    {
 
    @Override         //两个参数是泛型的对象
    public int compare(Student o1, Student o2) {
       //按照姓名的升序排列,前面加个负号就按照降序排列
       return o1.getAge()-o2.getAge();
    }
}
   
   

 

 

(4)对ArrayList进行排序


package com.xykj.comparatorTest;
import java.util.ArrayList;
import java.util.Collections;
public class MainClass {
    /**
     * comparator的使用  
     * */
    public static void main(String[] args) {
       ArrayList
   
   
    
     list = new ArrayList<>();
       list.add(new Student("1wenzhi", 18));
       list.add(new Student("3wenzhi", 19));
       list.add(new Student("2wenzhi", 33));
       list.add(new Student("66wenzhi", 10));
       list.add(new Student("4wenzhi", 18));
       System.out.println("=========排序前=======");
       for (Student student : list) {
           System.out.println(student);
       }
 
        // 按照年龄升序排列
       Collections.sort(list, new AgeSort());
       System.out.println("=========排序后=======");
 
       for (Student student : list) {
           System.out.println(student);
       }
    }
}
   
   


运行结果:



可以看到添加数乱序添加的,正常打印是按照添加的顺序打印的,排序后就可以得到想要的结果

 

 

 

(5)对LinkedList进行排序


package com.xykj.comparatorTest;
 
import java.util.Collections;
import java.util.LinkedList;
 
public class LinkedListMainClass {
   /**
    * comparator的使用
    * LinkedList和ArrayList使用方法一样的
* 这里显示按照姓名排列
    * */
   public static voidmain(String[] args) {
        LinkedList< Student> list=newLinkedList<>();
        list.add(new Student("1liwenzhi",18));
        list.add(new Student("3liwenzhi",19));
        list.add(new Student("2liwenzhi",33));
        list.add(new Student("88liwenzhi",10));
        list.add(new Student("66liwenzhi",18));
        System.out.println("=========排序前=======");
        for (Student student : list) {
           System.out.println(student);
        }
        //按照姓名升序排列
         Collections.sort(list,new NameSort());
        System.out.println("=========排序后=======");
          for (Student student : list) {
           System.out.println(student);
        }
   }
}


运行结果:



添加的顺序是杂乱的,排序后按照姓名的升序排列

 

 

Collections.sort方法只能对List接口下的实现类进行排序,对Set接口下的实现类不能进行排序,请看下面图片的示例:

 

 

 

三.最后的总结

(一)上面对Comparable接口和Comparator接口的使用方法和示例,都有很详细的描述。

(二)对java集合的各个实现类的排序方法也有比较详细的介绍。

(三)其实无论什么集合的数据通过一些方法都能排序,比如Set接口下的实现类的,可以把它们的数据先保存到List接口下的实现类里面,然后再通过Collections.sort的方法排序显示出来。

(四)排序在实际程序的应用也是很有用处的,比如显示显示商品按照距离最近来显示还是按照人气值来显示,都可以用排序来操作后显示。

(五)总而言之,至少要掌握一种排序方式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java集合排序方法comparable和comparator的总结 的相关文章

  • 外部硬件指纹扫描仪和 Android 设备集成

    我想建立一个android像员工考勤这样的应用程序使用fingerprint scanner 我想知道 是否可以使用外部硬件设备进行指纹识别 扫描 如何将Android应用程序与外部硬件finger集成 打印扫描设备 如何从外部硬件设备获取
  • 在多个不同线程之间共享变量

    我想在多个线程之间共享一个变量 如下所示 boolean flag true T1 main new T1 T2 help new T2 main start help start 我想分享flag在主线程和帮助线程之间 这是我创建的两个不
  • 使用祖父母接口的默认方法

    我完全不明白为什么这行不通 interface Test default void doMagic System out println Abracadabra class TestImpl implements Test class Sp
  • 构建 jar 后无法运行 exe

    我制作了一个简单的实用应用程序 其中我有一个要运行的exe文件 我通过使用它来运行 Runtime getRuntime exec this getClass getResource filename exe getPath 当我从 ide
  • Android 在 ROOM 数据库中插入大量数据

    我有大约 10 个模型 每个模型都有超过 120K 行和 90 列的记录 其中包含双数组值 在 Room 中插入任何模型都需要超过 125 130 秒 任何人都可以建议我需要做什么才能使用一些批量插入技术来保存所有这些 120K 该技术大约
  • Android - Firebase - 保存新数据而不覆盖旧数据

    创建此问题是因为我之前的问题包含 2 个问题 而不是将其缩小到 1 Aim 用户将能够存储新数据而不会覆盖之前提交的数据 描述 目前 当用户输入新报告时 事件报告节点中的用户事件报告数据将被覆盖 用户发送的旧事件报告中的数据应与新数据一起保
  • java IO将一个文件复制到另一个文件

    我有两个 Java io File 对象 file1 和 file2 我想将 file1 的内容复制到 file2 有没有一种标准方法可以做到这一点 而无需我创建一个读取 file1 并写入 file2 的方法 不 没有内置方法可以做到这一
  • Simplify-Ja​​va (by hgoebl) 减少点列表大小始终为 2 的问题

    我正在尝试实现减少算法https github com hgoebl simplify java https github com hgoebl simplify java 我查看了他的测试代码 并试图找出我认为正确的逻辑 我正在列出一份清
  • 二维数组中的寻路

    假设我有这个二维数组地图 0 0 0 0 7 1 1 1 1 1 1 1 1 0 7 7 7 7 1 1 1 24 1 1 1 1 0 7 24 24 24 24 24 24 24 1 1 3 1 0 7 23 23 23 23 23 23
  • 正则表达式的替代(流畅?)界面设计

    我刚刚看到了一个巨大的 Java 正则表达式 这让我对正则表达式的一般可维护性进行了一些思考 我相信大多数人 除了一些糟糕的 Perl 贩子 都会同意正则表达式很难维护 我正在考虑如何解决这种情况 到目前为止 我最有希望的想法是使用流畅的界
  • Postgres UUID 和休眠

    我有一个具有 UUID 列的实体 它不是主键 我正在使用 Postgres 和 hibernate 我对此专栏的类型是https www postgresql org docs 9 1 static datatype uuid html h
  • 如何正确安装mysqlconnecter java?

    上网冲浪后 我意识到我应该在系统环境变量中设置类路径连接器 jar 文件的路径文件我这样做了 并在命令行中输入此命令我有这个 C Users User gt echo classpath D classpath mysql connecto
  • 想要从 beanIO 字段名称标签在 csv 中写入标题

    我想在 csv 文件中写入标题 因为我的文本文件不包含任何标题 所以我想从 beanIO 字段名称标签写入它 我有一个 beanIO 有两个流 一个用于读取 另一个用于写入 这是输入文件 文本输入 txt 1 约翰 露 BA xxx1萨姆
  • Spring Boot,使用 EhCache 进行缓存

    我需要在我的应用程序中缓存一些数据 我正在考虑使用 Ehcache 我有几个问题 Ehcache需要另外一台服务器吗 我需要其他客户端来使用 Ehcache 吗 Ehcache 如何与多个实例配合使用 是否有可能使用 Ehcache 创建类
  • 如何为我的数独游戏制作 GUI? (摇摆)

    到目前为止 我已经编写了生成随机 9x9 数独网格的代码 我是Java的初学者 所以我有一些关于如何做UI的问题 显示数字的最佳方式是什么 我尝试创建 81 个 JTextFields 这非常乏味 而且我确信有一种有效的方法可以做到这一点
  • 使用 Hibernate 作为 ORM 机制的 Web 应用程序中的 L1 和 L2 缓存有什么区别?

    我只想要一些有关使用 L1 缓存和 L2 缓存的标准用途的一般信息 我很好奇 因为我正在研究使用赤土陶器作为二级缓存的系统 并且我发现它也有一级缓存 L1 缓存是每个 Hibernate 会话都存在的缓存 并且该缓存不在线程之间共享 该缓存
  • 如何从 Java 类调用 Kotlin 类

    我需要将意图从 java 活动传递到 Kotlin 活动 Java活动ProfileActivity class Intent selectGameIntent new Intent ProfileActivity this kotlin
  • 在同一项目上使用 Eclipse 和 NetBeans

    Eclipse 是一个非常棒的编辑器 我更喜欢使用它 但是缺少 Eclipse 的 GUI 设计工具 另一方面 NetBeans 非常适合 GUI 设计 在同一项目中使用 NetBeans 进行 GUI 设计和 Eclipse 进行其他所有
  • hibernate通过主键查询

    我想通过主键创建查询 假设我有类主键 PersonKey 属性是 name 和 id 我有 Person 类 属性是 PersonKey 地址 DOB 现在 我想通过主键搜索人员 首先 我创建 PersonKey 的实例 并将名称设置为 j
  • 我可以在方法体内使用注释吗?

    允许 Java 注释的语义将它们放置在某处在函数体内 例如注释特定的函数调用 语句或表达式 例如 class MyClass void theFunc Thing thing String s null Catching NullPoint

随机推荐

  • 使用Retrofit上传实体类到服务端(笔记)

    一 服务端 1 需要对参数用 RequestBody这个注解进行修饰 SpringBoot会自动将前端传过来的JSON数据反序列化成Java对象 登录 param requestVo return PostMapping value log
  • DOTA数据集标签txt文件转为xml文件

    文章目录 1 txt文件格式 2 xml文件格式 3 一般的txt到xml的转换思路 4 最终使用的txt到xml转换的脚本 5 之后可能用到的xml转换到txt的脚本 1 txt文件格式 DOTA数据集的txt文件格式如下 其中 每一行的
  • Springboot整合SpringSecurity

    使用Basic认证模式 1 maven依赖
  • 26.JavaWeb-SpringSecurity安全框架

    1 SpringSecurity安全框架 Spring Security是一个功能强大且灵活的安全框架 它专注于为Java应用程序提供身份验证 Authentication 授权 Authorization 和其他安全功能 Spring S
  • csv反序列化_序列化与反序列化

    toc 定义 序列化 将对象或数据结构转换成约定格式数据的过程 反序列化 将约定格式的数据转换成对象或数据结构的过程 通常我们将这种 约定格式的数据 称之为序列化协议 根据协议的特点序列化协议可以细分为文本序列化协议 以下简称文本协议 和二
  • 网线直连NUC调试并使用VSCode实现X11转发(Jetson,树莓派适用)

    1 场景描述 此种场景下 NUC与PC机通过一根网线进行连接 网线负责PC与NUC进行通信 SSH连接 同时可以将NUC的图形界面转发到PC 远程桌面或X11窗口转发均可 方便战队成员在没有显示器的场景下对NUC进行调试 配置示例如下图所示
  • springboot微服务前端传参数至后端的几个方式,@RequestBody如何传入多个参数@RequestParam

    一 问题 在接口测试工具中 常常要传入参数 初学者 也就是我菜鸡经常传错参数 不明白在Query还是Body里面传参 以及测试工具 AxxPoxx 测试下载接口的时候为什么发送数据成功却没有下载文档下来 后端参数传输方式 二 解决 quer
  • JNDI 资源

    第 6 章 JNDI 资源 Java 命名和目录接口 Java Naming and Directory Interface JNDI 是一种应用编程接口 application programming interface API 用于访问
  • "NO 3D support is available from the host"

    https forums opensuse org showthread php 494522 No 3d Support or graphics accelleration http askubuntu com questions 537
  • 【项目设计】高并发内存池 (四)[pagecache实现]

    C 学习历程 入门 博客主页 一起去看日落吗 持续分享博主的C 学习历程 博主的能力有限 出现错误希望大家不吝赐教 分享给大家一句我很喜欢的话 也许你现在做的事情 暂时看不到成果 但不要忘记 树 成长之前也要扎根 也要在漫长的时光 中沉淀养
  • 解决出现“raw.githubusercontent.com (raw.githubusercontent.com)

    服务器安装软件的时候出现 正在连接 raw githubusercontent com raw githubusercontent com 0 0 0 0 443 失败 拒绝连接 是因为改网址是被墙的 但是还是需要安装软件怎么办 打开多个地
  • 固态U盘量产:群联PS3111主控开卡量产工具使用教程

    PS3111开卡量产工具是一款专门用来进行量产的软件工具 下面将为大家提供使用教程 以帮助大家更加顺利地进行U盘量产 1 下载PS3111开卡量产工具 首先 需要在量产部落官网下载该工具并解压到电脑上 2 连接U盘 将需要进行量产的固态U盘
  • C++ opencv视频处理与保存

    1 视频属性类型 视频有很多的属性 有时长 分辨率 帧宽度 帧高度 帧速率等 视频属性中 由于国内互联网视频网站的定义 我们对分辨率的区分有些误区 所以这里重新介绍一下视频的分辨率 至于其他属性 一般不会有什么误区 分辨率 通常国际标准 我
  • 大语言模型高质量提示词最佳实践

    大语言模型高质量提示词最佳实践 一 提供更清晰的指令 使用大语言模型 类似ChatGPT Bard等工具 的过程中 一个关键的技巧是能够给出清晰和明确的指令 大语言模型的运作方式是根据提供的输入 预测接下来应该生成什么内容 因此 给出明确的
  • Vue的UI网页创建和引入Element组件

    第一步 新创建一个文件夹用来生成vue项目 第二步 进入这个文件夹 在路径栏输入CMD打开DOS窗口 第三步 打开cmd窗口 输入命令 vue ui 第四步 输入命令后运行 浏览器会自动打开vue ui 网页 第五步 点击仪表盘上方的文本框
  • Keepalived--05--脑裂问题

    一 问题 1 1 场景 高可用 在高可用 HA 系统中 当联系2个节点的 心跳线 断开时 本来为一整体 动作协调的HA系统 就分裂成为2个独立的个体 由于相互失去了联系 都以为是对方出了故障 两个节点上的HA软件像 裂脑人 一样 争抢 共享
  • 在TensorFlow中使用自定义数据集训练自己的模型

    在TensorFlow中使用自定义数据集训练自己的模型 写在前面的话 一 自定义数据集的目录结构 以今年电赛数字识别为例 二 在TensorFlow中读取数据集 2 1 纯手工打造 2 1 1 获取所有图片的路径 2 1 2 获取标签并转换
  • PCB结构和谐振(三)

    PCB结构和谐振 一 PCB结构和谐振 二 仿真研究 在本节中 我们首先对玻璃束的随机分布进行了简单的模拟研究 然后我们利用这些实验结论来简化常用的玻璃布3D结构 最后 这种简化的结构用于研究复杂层压板和两个周期性布局设计的谐振 玻璃束的随
  • git 连接gitee时报错 Auth error: Access deined: authorize failure. fatal: Could not read from remote repos

    这是个特别坑的错误 但是我找了很久 是可以当笑话看了 把ssh公钥添加好 并且进行remote远程库的连接 这两个是基本操作 网上有很多帖子都介绍的很详细 这里就不罗嗦了 说一下我这次的坑爹的情况 我从头到尾把步骤都仔仔细细排查了好几遍 结
  • Java集合排序方法comparable和comparator的总结

    Java集合排序方法的总结 接口comparable和接口comparator的比较 一 相关概念 Comparable和Comparator都是用来实现集合中元素的比较 排序的 一 Comparable Comparable是在集合内部定