当前位置: 首页 > news >正文

Java 8 排序

今天分享 Java 8 进行排序的 10 个姿势,其实就是把 Java 8 中的 Lambda、Stream、方法引用等知识点串起来

传统排序

现在有一个 List 集合:

public static List<User> LIST = new ArrayList() {{add(new User("Lisa", 23));add(new User("Tom", 11));add(new User("John", 16));add(new User("Jessie", 26));add(new User("Tony", 26));add(new User("Messy", 26));add(new User("Bob", 19));add(new User("Yoga", 65));}
};

jdk8 之前的排序:

/*** jdk8 之前的排序*/
private static void sortPreJdk8() {System.out.println("=====jdk8 之前的排序=====");List<User> list = new ArrayList<>(LIST);Collections.sort(list, new Comparator<User>() {@Overridepublic int compare(User u1, User u2) {return u1.getAge().compareTo(u2.getAge());}});for (User user : list) {System.out.println(user);}System.out.println();
}

Java 8 中的排序

1、Lambda 排序(带参数类型) Java 8 中的 List 接口新增了一个 sort 默认方法:
在这里插入图片描述
接收 Comparator 接口参数,这个接口在 Java 8 中被修饰为函数式接口:
在这里插入图片描述
然后我们就可以把 Comparator 接口参数改成了用 Lambda 表达式的形式,用 Lambda 表达式干掉了匿名内部类,让代码更简洁。

使用示例如下:

/*** jdk8 lambda 排序,带参数类型*/
private static void sortWithJdk8Lambda1() {System.out.println("=====jdk8 lambda 排序,带参数类型=====");List<User> list = new ArrayList<>(LIST);list.sort((User u1, User u2) -> u1.getAge().compareTo(u2.getAge()));list.forEach(System.out::println);System.out.println();
}

2、Lambda 排序(不带参数类型)
Lambda 表达式是可以不用带参数类型的,如下示例:

/*** jdk8 lambda 排序,不带参数类型*/
private static void sortWithJdk8Lambda2() {System.out.println("=====jdk8 lambda 排序,不带参数类型=====");List<User> list = new ArrayList<>(LIST);list.sort((u1, u2) -> u1.getAge().compareTo(u2.getAge()));list.forEach(System.out::println);System.out.println();
}

代码中的 u1, u2 并没有用 User 类修饰,它会自动推断为 User 类型,因为集合本身就是一个 User 泛型。

3、静态方法引用排序
除了 Lambda 表达式,还可以用类的静态方法引用:

/*** jdk8 静态方法引用排序*/
private static void sortWithJdk8StaticMethodRef() {System.out.println("=====jdk8 静态方法引用排序=====");List<User> list = new ArrayList<>(LIST);list.sort(User::compareAge);list.forEach(System.out::println);System.out.println();
}

使用方法引用之后代码是不是更简洁了?

4、实例方法引用排序
不仅可以用类的静态方法,还可以用类的实例普通方法引用:

/*** jdk8 实例方法引用排序*/
private static void sortWithJdk8InstanceMethodRef() {System.out.println("=====jdk8 实例方法引用排序=====");List<User> list = new ArrayList<>(LIST);list.sort(User.getInstance()::compare);list.forEach(System.out::println);System.out.println();
}

这个 getInstance 在这里实际上是一个单例,但和单例无关,任何类的实例都可以。

另外,这些知识点我也整理到了小程序,都是面试常考的,大家可以在Java面试库小程序在线刷题。

5、Comparator 工具类排序(升序)
Java 8 在 Comparator 接口中新增了 comparing 方法:
在这里插入图片描述
这个工具方法需要提供一个函数式接口参数,也就是要比较的哪个字段,最后还是返回 Comparator 接口实例。

使用示例如下:

/*** jdk8 升序排序,Comparator 提供的静态方法*/
private static void sortWithJdk8ComparatorAsc() {System.out.println("=====jdk8 升序排序=====");List<User> list = new ArrayList<>(LIST);list.sort(Comparator.comparing(User::getAge));//  list.sort(Comparator.comparing((user) -> user.getAge()));list.forEach(System.out::println);System.out.println();
}

既然是函数式接口,所以又可以用 Lambda、方法引用形式作为参数传入。

6、Comparator 工具类排序(降序)
还可以使用 Comparator.reversed/ reversedOrder 方法进行降序:

/*** jdk8 Comparator 工具类排序(降序)*/
private static void sortWithJdk8ComparatorDesc() {System.out.println("=====jdk8 降序降序=====");List<User> list = new ArrayList<>(LIST);list.sort(Comparator.comparing(User::getAge).reversed());list.forEach(System.out::println);System.out.println();
}

7、组合排序
如果要先按用户的年龄排序,年龄相同的再按姓名排序,可以使用 Comparator 接口中的 thenComparing 默认方法:

private static void sortGroupWithJdk8() {System.out.println("=====jdk8 组合排序=====");List<User> list = new ArrayList<>(LIST);list.sort(Comparator.comparing(User::getAge).thenComparing(User::getName));list.forEach(System.out::println);System.out.println();
}

输出结果:
在这里插入图片描述
注意年龄 26 岁的人又按姓名按自然顺序排序了。

8、Stream 排序
还可以把 List 集合转换为 Stream,然后使用其 sorted 方法:
在这里插入图片描述
sorted 方法也是接收 Comparator 接口参数,所以我们也可以使用 Lambda、方法引用、Comparator 接口自身提供的工具方法对其调用:

/*** jdk8 Stream 排序*/
private static void sortWithJdk8Stream() {System.out.println("=====jdk8 Stream 排序=====");List<User> list = new ArrayList<>(LIST);list = list.stream().sorted(User::compareAge).collect(Collectors.toList());//  list = list.stream().sorted((u1, u2) -> u1.getAge().compareTo(u2.getAge())).collect(Collectors.toList());//  list = list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());list.forEach(System.out::println);System.out.println();
}

所以使用 Stream 也可以扩展多种排序方法,见注释部分,这里就不展开了。另外,Stream 系列我之前写过一个专题了,这里不再展开,不懂的关注公众号Java技术栈,然后在公众号 Java 教程菜单中阅读。

9、并行 Stream 排序
有 Stream 排序,那就并行 Stream(parallelStream)排序:

/*** jdk8 并行 Stream 排序*/
private static void sortWithJdk8parallelStream() {System.out.println("=====jdk8 Stream 排序=====");List<User> list = new ArrayList<>(LIST);list = list.parallelStream().sorted(User::compareAge).collect(Collectors.toList());list.forEach(System.out::println);System.out.println();
}

10、Collections 排序
既然在 Java 8 中,Comparator 接口被定义成了函数式接口,那么我们传统的 Collections 工具类就可以改变了,我们也可以使用 Lambda、方法引用、Comparator 接口自身提供的工具方法对其调用:

/*** jdk8 Collections 排序*/
private static void sortWithCollections() {System.out.println("=====jdk8 Collections 排序=====");List<User> list = new ArrayList<>(LIST);Collections.sort(list, User::compareAge);//  Collections.sort(list, (u1, u2) -> u1.getAge().compareTo(u2.getAge()));
//  Collections.sort(list, Comparator.comparing(User::getAge));    list.forEach(System.out::println);System.out.println();
}

总结

本文列举了 Java 8 中的 10 种排序方法,其实就是 10 个案例,还可以扩展更多,只是给大家个参考,总体来说,其实可以分为 3 大类:

List 接口中的 sort 方法

Stream 接口中的 sorted 方法

Collections.sort 工具类方法

这三个方法都可以接收 Comparator 接口作为参数,并且 Comparator 接口在 Java 8 中被定义成了函数式接口,所以我们可以用 Lambda 表达式、方法引用、Comparator 自身工具类等不同的参数形式传入,可谓是太秀了。

这些方法性能如何呢?

写了一个小例子,1 万数据的集合,使用静态方法引用进行测试:

long start = System.currentTimeMillis();
List<User> list1 = new ArrayList<>(list);
list1.sort(User::compareAge);
System.out.println("List.sort: " + (System.currentTimeMillis() - start));start = System.currentTimeMillis();
List<User> list2 = new ArrayList<>(list);
Collections.sort(list2, User::compareAge);
System.out.println("Collections.sort: " + (System.currentTimeMillis() - start));start = System.currentTimeMillis();
List<User> list3 = new ArrayList<>(list);
list3.stream().sorted(User::compareAge).collect(Collectors.toList());
System.out.println("Stream.sorted: " + (System.currentTimeMillis() - start));

输出结果:

List.sort: 18 Collections.sort: 18 Stream.sorted: 48
tream 要略慢,因为多了两道转换的工序,但如果不是特别大的数据量,比如 1000 条数据的集合,这 3 个几乎性能一样,基本都在 1 毫秒内完成排序,对于普通小数据的排序可以闭着眼睛用了。

相关文章:

Java 8 排序

今天分享 Java 8 进行排序的 10 个姿势&#xff0c;其实就是把 Java 8 中的 Lambda、Stream、方法引用等知识点串起来 传统排序 现在有一个 List 集合&#xff1a; public static List<User> LIST new ArrayList() {{add(new User("Lisa", 23));add(new Us…...

Blazor_WASM之4:路由

Blazor_WASM之4&#xff1a;路由 路由模板 通过 Router组件可在 Blazor 应用中路由到 Razor 组件。 Router 组件在 Blazor 应用的 App 组件中使用。App组件模板如下 <Router AppAssembly"typeof(Program).Assembly"><Found Context"routeData"…...

对Vue响应式的理解

1. 啥是响应式? &#xff08;1&#xff09;.所谓的数据响应式就是能够使数据变化可以被检测到并且对这种变化做出响应式的机制 2. 为什么vue需要响应式? &#xff08;1&#xff09;.MVVM框架中要解决的核心问题数据驱动视图&#xff0c;数据的改变引起视图的更新&#xff…...

磁盘阵列Raid探讨

最近公司买服务器&#xff0c;顺便了解一下服务器配置方面的问题 以下讨论的都是入门级服务器配置&#xff0c;全部是主观意见&#xff0c;没有任何科学依据&#xff0c;欢迎大家讨论 Raid0&#xff0c;Raid1&#xff0c;Raid10&#xff0c;Raid5&#xff0c;Raid6(Raid5热备)…...

基于MyBatis依次、批量、分页增删改查

我们知道处理数据有三种思路&#xff1a;依次、批量、分页&#xff0c;对应方法如下 依次处理&#xff1a;在 Java 里面写 for 循环&#xff0c;依次使用 SQL 语句&#xff0c;频繁连接断开数据库批量处理&#xff1a;在 MyBatis 里面用 <foreach> 拼接成一条长 SQL 语句…...

Tomcat源码分析-Session源码解析

tomcat session 设计分析 tomcat session 组件图如下所示&#xff0c;其中 Context 对应一个 webapp 应用&#xff0c;每个 webapp 有多个 HttpSessionListener&#xff0c; 并且每个应用的 session 是独立管理的&#xff0c;而 session 的创建、销毁由 Manager 组件完成&…...

常见数据模型

目录 1.1两类数据模型 1.2概念模型 1.3数据模型的组成要素 1.4常见数据模型 层次模型 网状模型 关系模型 数据模型是对现实世界数据特征的抽象&#xff0c;也就是说数据模型是用来描述数据、组织数据和对数据进行操作的。数据模型是数据库系统的核心和基础。 1.1两类数…...

Lesson 8.3 ID3、C4.5 决策树的建模流程 Lesson 8.4 CART 回归树的建模流程与 sklearn 参数详解

文章目录一、ID3 决策树的基本建模流程二、C4.5 决策树的基本建模流程1. 信息值&#xff08;information value&#xff09;2. C4.5 的连续变量处理方法三、CART 回归树的基本建模流程1. 数据准备2. 生成备选规则3. 挑选规则4. 进行多轮迭代5. 回归树的预测过程四、CART 回归树…...

阿里云手机短信登录

阿里云短信服务介绍阿里云短信服务&#xff08;Short Message Service&#xff09;是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手&#xff0c;即可发送验证码、通知类和营销类短信&#xff1b;国内验证短信秒级触达&#xff0c;到达率最高可达99%&…...

Android Camera SDK NDK NDK_vendor介绍

Android Camera JNI NDK NDK_vendor介绍前言主要有哪几种interface&#xff1f;Android SDKCamera API 1Camera API 2小结Android NDKNDK InterfaceNDK Vendor Interface小结Camera VTS Testcase总结Reference前言 本篇博客是想介绍Android camera从application layer到camera…...

SQL基础语句小结

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; 目录 一、SQL概述 1.简介 2.格式语法 3.SQL分类 二、DDL操作数据库 1.创建数据库 2.查询与使用 3.删除数据库 三、DDL:操作表 (1)数据类型 (2)创建表 (3)查询当前数据库的表 (4)删除表 (5)修改表 四、DML…...

管理类书籍推荐

管理类书籍对于每一位想要获得管理能力提升或者实现职业生涯更上一层楼的企业管理者或领导者而言&#xff0c;都是不可或缺的一项重要学习工具。作为管理工作从事者的职场必需品&#xff0c;一本出色的管理类书籍可以为我们提供大量宝贵的经验与专业建议&#xff0c;从而让管理…...

win10 mingw 调用python

ubuntu调用pythonhttps://blog.csdn.net/qq_39942341/article/details/129333969 我这里mingw是用msys2的 opencv也是msys2装的 安装msys2和opencv可以参考这个https://blog.csdn.net/qq_39942341/article/details/129380197?spm1001.2014.3001.5502 环境变量里加入python路…...

教你使用三种方式写一个最基本的spark程序

当需要处理大规模数据并且需要进行复杂的数据处理时&#xff0c;通常会使用Hadoop生态系统中的Hive和Spark来完成任务。在下面的例子中&#xff0c;我将说明如何使用Spark编写一个程序来处理Hive中的数据&#xff0c;以满足某个特定需求。假设我们有一个Hive表&#xff0c;其中…...

软件设计师错题集

软件设计师错题集一、计算机组成与体系结构1.1 浮点数1.2 Flynn分类法1.3 指令流水线1.4 层次化存储体系1.4.1 程序的局限性1.5 Cache1.6 输入输出技术1.7 总线系统1.8 CRC循环冗余校验码二、数据结构与算法基础2.1 队列与栈2.2 树与二叉树的特殊性2.3 最优二叉树&#xff08;哈…...

【华为机试真题详解 Python实现】静态扫描最优成本【2023 Q1 | 100分】

文章目录前言题目描述输入描述输出描述示例 1输入&#xff1a;输出&#xff1a;示例 2输入&#xff1a;输出&#xff1a;题目解析参考代码前言 《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试&#xff0c;期间有想了解的…...

算法刷题总结 (四) 动态规划

算法总结4 动态规划一、动态规划1.1、基础问题11.1.1、509. 斐波那契数列1.1.2、70. 爬楼梯1.1.3、746. 使用最小花费爬楼梯1.2、基础问题21.2.1、62. 不同路径1.2.2、63. 不同路径Ⅱ1.2.3、343. 整数拆分1.2.4、96. 不同的二叉搜索树1.3、背包问题1.3.1、01背包1.3.1.1、单次选…...

Grafana 转换数据的工具介绍

转换数据 Grafana 可以在数据显示到面板前对数据进行处理 1、点击Transform选项卡 2、选择要使用的转换类型&#xff0c;不同的转换类型配置不同 3、要新增转换类型&#xff0c;点击Add transformation 4、使用右上角调式按钮可以调式转换 支持的转换类型&#xff1a; Add f…...

Linux 学习笔记

一、 概述 1. 操作系统 ① 计算机由硬件和软件组成 ② 操作系统属于软件范畴&#xff0c;主要作用是协助用户调度硬件工作&#xff0c;充当用户和计算机硬件之间的桥梁 ③ 常见的操作系统 &#x1f920; PC端&#xff1a;Windows、Linux、MacOS&#x1f920; 移动端&#…...

HTML注入专精整理

目录 HTML注入介绍 抽象解释 HTML注入的影响 HTML注入与XSS的区别 HTML元素流程图...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...