java 排序 详解
Java 提供了多种方式对数据进行排序,包括数组和集合的排序。排序在日常开发中非常常见,以下将从排序算法的基本原理、Java 中的内置排序方法以及自定义排序三方面进行详解。
1. 排序的基本概念
排序是将一组数据按特定顺序排列的过程,常见顺序包括:
- 升序:从小到大排列(如:1, 2, 3, …)。
- 降序:从大到小排列(如:10, 9, 8, …)。
常见排序算法及其时间复杂度
| 排序算法 | 时间复杂度(平均) | 时间复杂度(最坏) | 空间复杂度 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 (Bubble Sort) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 |
| 插入排序 (Insertion Sort) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 |
| 选择排序 (Selection Sort) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 |
| 快速排序 (Quick Sort) | O ( n log n ) O(n \log n) O(nlogn) | O ( n 2 ) O(n^2) O(n2) | O ( log n ) O(\log n) O(logn) | 不稳定 |
| 归并排序 (Merge Sort) | O ( n log n ) O(n \log n) O(nlogn) | O ( n log n ) O(n \log n) O(nlogn) | O ( n ) O(n) O(n) | 稳定 |
| 堆排序 (Heap Sort) | O ( n log n ) O(n \log n) O(nlogn) | O ( n log n ) O(n \log n) O(nlogn) | O ( 1 ) O(1) O(1) | 不稳定 |
2. Java 中的内置排序方法
Java 提供了丰富的内置排序方法,主要通过 Arrays 和 Collections 两个工具类实现。
(1) 使用 Arrays.sort 方法(针对数组)
用法
- 基础类型数组:直接使用。
- 引用类型数组:可以传入自定义比较器。
示例代码
import java.util.Arrays;public class ArraySortExample {public static void main(String[] args) {// 基础类型数组排序int[] numbers = {5, 2, 8, 1, 3};Arrays.sort(numbers); // 默认升序System.out.println("基础类型排序后:" + Arrays.toString(numbers));// 引用类型数组排序String[] words = {"apple", "banana", "cherry", "date"};Arrays.sort(words); // 默认按字典序排序System.out.println("引用类型排序后:" + Arrays.toString(words));// 自定义排序(降序)Arrays.sort(words, (a, b) -> b.compareTo(a));System.out.println("自定义排序后:" + Arrays.toString(words));}
}
输出结果
基础类型排序后:[1, 2, 3, 5, 8]
引用类型排序后:[apple, banana, cherry, date]
自定义排序后:[date, cherry, banana, apple]
特点
Arrays.sort使用 双轴快速排序(Dual-Pivot Quicksort)实现,时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)。- 对基础类型排序效率极高,但对引用类型需要更多内存。
(2) 使用 Collections.sort 方法(针对集合)
用法
- 专为
List设计(如ArrayList、LinkedList等)。 - 可以使用默认排序(元素需实现
Comparable接口)或自定义比较器。
示例代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class CollectionSortExample {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>();numbers.add(5);numbers.add(2);numbers.add(8);numbers.add(1);numbers.add(3);// 默认升序排序Collections.sort(numbers);System.out.println("默认排序后:" + numbers);// 自定义排序(降序)Collections.sort(numbers, (a, b) -> b - a);System.out.println("自定义排序后:" + numbers);}
}
输出结果
默认排序后:[1, 2, 3, 5, 8]
自定义排序后:[8, 5, 3, 2, 1]
特点
Collections.sort内部调用List的sort方法,底层使用 TimSort 算法。- 稳定排序,适合复杂对象的排序。
(3) 使用 List.sort 方法
从 Java 8 开始,List 接口新增了 sort 方法,可以直接传入比较器。
示例代码
import java.util.ArrayList;
import java.util.List;public class ListSortExample {public static void main(String[] args) {List<String> words = new ArrayList<>();words.add("apple");words.add("banana");words.add("cherry");words.add("date");// 默认升序words.sort(String::compareTo);System.out.println("默认排序后:" + words);// 自定义排序(按长度降序)words.sort((a, b) -> b.length() - a.length());System.out.println("按长度降序排序后:" + words);}
}
输出结果
默认排序后:[apple, banana, cherry, date]
按长度降序排序后:[banana, cherry, apple, date]
3. 自定义排序
对于复杂对象,需要使用 Comparable 或 Comparator 来定义排序规则。
(1) 使用 Comparable 接口
Comparable 接口用于定义自然排序,需实现其 compareTo 方法。
示例代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;class Student implements Comparable<Student> {String name;int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic int compareTo(Student other) {return this.score - other.score; // 按分数升序}@Overridepublic String toString() {return name + ": " + score;}
}public class ComparableExample {public static void main(String[] args) {List<Student> students = new ArrayList<>();students.add(new Student("Alice", 85));students.add(new Student("Bob", 92));students.add(new Student("Charlie", 78));Collections.sort(students);System.out.println("按分数升序排序:" + students);}
}
输出结果
按分数升序排序:[Charlie: 78, Alice: 85, Bob: 92]
(2) 使用 Comparator 接口
Comparator 接口用于定义外部排序规则,可以灵活调整排序逻辑。
示例代码
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;class Student {String name;int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return name + ": " + score;}
}public class ComparatorExample {public static void main(String[] args) {List<Student> students = new ArrayList<>();students.add(new Student("Alice", 85));students.add(new Student("Bob", 92));students.add(new Student("Charlie", 78));// 按分数降序排序students.sort((a, b) -> b.score - a.score);System.out.println("按分数降序排序:" + students);// 按名字字母升序排序students.sort(Comparator.comparing(s -> s.name));System.out.println("按名字升序排序:" + students);}
}
输出结果
按分数降序排序:[Bob: 92, Alice: 85, Charlie: 78]
按名字升序排序:[Alice: 85, Bob: 92, Charlie: 78]
4. 常见排序陷阱与优化
- 稳定性问题:
- 对于需要保持原始顺序的排序,使用稳定排序算法(如
Collections.sort和TimSort)。
- 对于需要保持原始顺序的排序,使用稳定排序算法(如
- 性能优化:
- 对小规模数组使用插入排序或冒泡排序。
- 对大规模数据使用快速排序或归并排序。
- **
避免多次比较**:- 使用
Comparator.comparing链式调用时避免重复字段比较。
- 使用
5. 总结
- 数组排序:使用
Arrays.sort,适合基础类型和简单对象。 - 集合排序:使用
Collections.sort或List.sort,适合复杂对象和灵活排序需求。 - 自定义排序:通过
Comparable和Comparator实现,灵活定义规则。 - 排序算法:根据数据规模和需求选择合适的排序算法。
Java 内置的排序方法效率高、使用方便,但理解其底层原理和优化策略可以帮助开发者更好地应对复杂排序需求。
相关文章:
java 排序 详解
Java 提供了多种方式对数据进行排序,包括数组和集合的排序。排序在日常开发中非常常见,以下将从排序算法的基本原理、Java 中的内置排序方法以及自定义排序三方面进行详解。 1. 排序的基本概念 排序是将一组数据按特定顺序排列的过程,常见顺…...
【数据集】城市通量塔站点观测数据
【数据集】城市通量塔站点观测数据 数据概述数据下载参考数据概述 数据集简介:Harmonized gap-filled dataset from 20 urban flux tower sites 数据集名称:Harmonized gap-filled dataset from 20 urban flux tower sites (用于 Urban-PLUMBER 项目的 20 个城市通量塔站点…...
scau编译原理综合性实验
一、题目要求 题目: 选择部分C语言的语法成分,设计其词法分析程序、语法语义分析程序。 要求: 设计并实现一个一遍扫描的词法语法语义分析程序,将部分C语言的语法成分(包含赋值语句、if语句、while循环语句…...
ETAS工具导入DBC生成Com协议栈
文章目录 前言DBC配置关键属性Cobra参数配置Cobra使用isolar工程配置总结前言 ETAS工具导入DBC主要也是生成arxml用的,ETAS推荐使用Cobra导入,本文介绍导入过程及注意事项 DBC配置关键属性 对于普通Com报文,配置为周期发送,及其周期,NmMessage配置为No,示例如下: 对…...
表单校验规则
这里简单记录下vue使用表单时候,给表单添加校验规则,直接上代码 <script setup>import { ref } from vue// 定义表单对象const form ref({account: ,password: ,agree: true})// 定义表单验证规则const rules {account: [{required: true, mess…...
接口的扩展
1. 接口中新增的方法 JDK7之前接口中只能定义抽象方法。 JDK8的新特性:接口中可以定义有方法体的方法。(默认、静态) JDK9的新特性:接口中可以定义有私有方法体的方法。 有方法体的方法:接口升级时,为了兼容…...
新能源电机轴承电腐蚀,如何破?
近年来,随着全球范围内对可再生能源的重视与推动,新能源电机作为新能源汽车、风力发电和太阳能发电等系统的重要组成部分,得到了迅猛的发展。然而,在实际应用中,新能源电机的维护与管理越来越受到关注,其中…...
Java中的File和IO流
File对象 File对象本质是一个文件或文件夹,用于写入和读取文件内容 注意:对于相对路径而言,在单元测试方法中的File是相对于Module,在main中的File是相对于Project 构造器 File(String pathname)File file1 new File("D:…...
ls命令实操笔记
ls命令:全称list,显示文件的文件名与相关属性。(目前工作目录所含之文件及子目录) 4567 45678 7891 a1b2 a2b3c abcd Abcd acde aD7E bcde 通过ls浏览上述文件所在的目录,实现以下需求: 浏览含…...
线段数--算法
线段树是常用来维护 区间信息 的数据结构 线段树可以在 O(logN) 的时间复杂度内实现 单点修改区间修改区间查询 区间求和求区间最大值求区间最小值 简单介绍一下线段树 线段树是一个将区间内的数不断细分的一种数据结构,也就是一个完全二叉树,用每一…...
JS的DOM操作和事件监听综合练习 (具备三种功能的轮播图案例)
下面是是对dom操作的一个综合练习 下面代码是html的基本骨架(没有任何的功能): <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" c…...
低温存储开关机问题
问题: 某消费电子产品在进行可靠性实验室,在低温-30C存储两个小时后,上电不开机。在常温25C时,开关机正常。 分析: 1、接串口抓log信息,从打印信息可以看出uboot可以起来,在跑kernel时&#x…...
mysql系列1—mysql架构和协议介绍
背景: 本文开始整理mysql相关的文章,用于收集数据库相关内容;包括mysql架构和存储方式、索引结构和查询优化、数据库锁等内容。思考如何根据具体的业务给出最优的分表规划和表设计、字段选择和索引设计、优化的SQL语句,以及数据库…...
设计模式——模板模式
定义与基本概念 模板模式(Template Pattern)是一种行为设计模式。它在一个抽象类中定义了一个操作的算法骨架,将一些步骤的实现延迟到具体子类中。这个抽象类就像是一个模板,定义了执行某个流程的基本框架,而具体的细…...
CV22_语义分割基础
1. 常见的分割类型 在计算机视觉领域,根据不同的应用场景和需求,分割任务可以分为几种主要类型。以下是几种常见的分割类型: 语义分割(Semantic Segmentation): 语义分割的目标是将图像中的每个像素分配到…...
Dubbo源码解析-Dubbo的线程模型(九)
一、Dubbo线程模型 首先明确一个基本概念:IO 线程和业务线程的区别 IO 线程:配置在netty 连接点的用于处理网络数据的线程,主要处理编解码等直接与网络数据 打交道的事件。 业务线程:用于处理具体业务逻辑的线程,可以…...
【Canvas与标志】圆角三角形生化危险警示标志
【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>圆角三角形生化危险警示标志 Draft1</title><style type&qu…...
解决Dcat Admin laravel框架登录报错问题,(blocked:mixed-content)
前言 在使用 Dcat Admin 后台登录时,发生 error 报错:(blocked:mixed-content) xhr VM484:1,浏览器拦截 其实这是浏览器在 HTTPS 页面中尝试加载 HTTP 资源,导致浏览器阻止了这些不安全的请求。 解决 在 .env 文件中添加或修改 AD…...
(三)Sping Boot学习——升级jdk1.8-jdk18
1.修改系统环境变量。 2.idea中修改配置。 3.项目setting中设置修改 4.更新后还要重新下载依赖mvn clean install ,并且记住reload 项目。同时查看java -version查看一下jdk版本。...
语言模型中的多模态链式推理
神经网络的公式推导 简介摘要引言多模态思维链推理的挑战多模态CoT框架多模态CoT模型架构细节编码模块融合模块解码模块 实验结果运行代码补充细节安装包下载Flan-T5数据集准备rougenltkall-MiniLM-L6-v2运行 简介 本文主要对2023一篇论文《Multimodal Chain-of-Thought Reason…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
