Java21 LTS版本
一、前言
除了众所周知的 JEP 之外,Java 21 还有更多内容。首先请确认 java 版本:
$ java -version
openjdk version "21" 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)
我们一起来看看 String 和它的朋友们 Collections、Date、Time、HttpClient、并发、Math 和 BigInteger 的新增一些 API。
二、String(Java21新增)
String 新增了 indexOf() 方法,允许在起始索引和结束索引之间查找单个字符或子字符串。
public int indexOf(int ch, int beginIndex, int endIndex);
public int indexOf(String str, int beginIndex, int endIndex);
示例:
String text = "牛牛帮";int index = text.indexOf("0", 5, 15);
三、Character(Java21新增)
Character 类新增了几个方法来支持 Emoji 表情符号,新增了五个方法:isEmoji()、isEmojiComponent()、isEmojiModifier()、isEmojiModifierBase() 和 isEmojiPresentation()。
public static boolean isEmoji(int codePoint);
public static boolean isEmojiPresentation(int codePoint);
public static boolean isEmojiModifier(int codePoint);
public static boolean isEmojiModifierBase(int codePoint);
public static boolean isEmojiComponent(int codePoint);
public static boolean isExtendedPictographic(int codePoint);
所有这些方法都接受一个 int 类型的码点作为参数,判断传入的码点是否具有对应的表情符号。
四、StringBuffer 和 StringBuilder(Java21新增)
StringBuffer 和 StringBuilder 新增了 repeat() 方法重复单个字符或字符串多次。
StringBuilder:
@Override
public StringBuilder repeat(int codePoint, int count);@Override
public StringBuilder repeat(CharSequence cs, int count);
StringBuffer:
@Override
public synchronized StringBuffer repeat(int codePoint, int count);@Override
public synchronized StringBuffer repeat(CharSequence cs, int count);
五、Charset(Java18)
Charset 新增了一个带 fallback 的 forName()方法。
public static Charset forName(String charsetName, Charset fallback);
六、正则分组优化(Java20)
提取地址中的省市区县,代码如下:
笔者有幸用过正则分组,需求是提取地址中的省市区县,代码如下:private static final Pattern PATTERN = Pattern.compile("(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?<county>[^县]+县|.+区|.+市|.+旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<village>.*)");public static Map<String, String> getAddressResolution(String address) {Matcher matcher = PATTERN.matcher(address);String province, city, county, town, village;Map<String, String> row = new HashMap<>();while (matcher.find()) {province = matcher.group("province");row.put("province", province == null ? "" : province.trim());city = matcher.group("city");row.put("city", city == null ? "" : city.trim());county = matcher.group("county");row.put("county", county == null ? "" : county.trim());town = matcher.group("town");row.put("town", town == null ? "" : town.trim());village = matcher.group("village");row.put("village", village == null ? "" : village.trim());}return row;
}public static void main(String[] args) {String address = "湖南省长沙市岳麓区永青路668号";System.out.println(getAddressResolution(address));// {province=湖南省, city=长沙市, county=岳麓区, town=, village=永青路668号}
}
Matcher、MatchResult、Pattern 现在新增了 namedGroups() 相关方法, getAddressResolution() 方法简化成这样了:
public static Map<String, String> getAddressResolution(String address) {Matcher matcher = PATTERN.matcher(address);Map<String, String> row = new HashMap<>();if (matcher.matches()) {Map<String, Integer> groupMap = matcher.namedGroups();groupMap.forEach((key, group) -> row.put(key, matcher.group(group)));}return row;
}
七、集合
Collections 框架中添加了 SequencedCollection、SequencedSet 和 SequencedMap 三个接口(Java21 新增)。
interface SequencedCollection<E> extends Collection<E> {// new methodSequencedCollection<E> reversed();// methods promoted from Dequevoid addFirst(E);void addLast(E);E getFirst();E getLast();E removeFirst();E removeLast();
}interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {SequencedSet<E> reversed(); // covariant override
}interface SequencedMap<K,V> extends Map<K,V> {// new methodsSequencedMap<K,V> reversed();SequencedSet<K> sequencedKeySet();SequencedCollection<V> sequencedValues();SequencedSet<Entry<K,V>> sequencedEntrySet();V putFirst(K, V);V putLast(K, V);// methods promoted from NavigableMapEntry<K, V> firstEntry();Entry<K, V> lastEntry();Entry<K, V> pollFirstEntry();Entry<K, V> pollLastEntry();
}
添加这 3 个新接口后,Java 集合类图发生了变化,图示:

除了这些,现在还可以使用多个工厂方法创建具有给定初始容量的不同类型的 Map(Java19新增)。
HashMap.newHashMap(100);
HashSet.newHashSet(100);
LinkedHashMap.newLinkedHashMap(100);
LinkedHashSet.newLinkedHashSet(100);
WeakHashMap.newWeakHashMap(100);
Map 创建看起来很简单,但实际上却有一些技巧。例如,HashMap 内部是基于数组构建的,当该数组装满时,它会被复制到一个更大的数组中。所以阿里《JAVA开发手册》也建议设置 HashMap 的初始容量。问题在于,实际上并不仅仅是复制,第一个数组的所有键值对都需要重新计算哈希值,以便放置在新数组的正确位置上。由于哈希值的计算取决于数组的大小,每个数组的存储位置很可能不同。因此,我们不能简单地将第一个数组的内容复制到第二个数组中。为了避免冲突,当数组达到 75% 的容量时,就被认为已经满了。因此,要创建一个可以存储 100 个键值对的 Map,实际上需要一个大小为 134 的数组。考虑到数组的大小必须是 2 的次方,因此实际上会创建一个大小为 256 的数组。这种计算很容易出错,所以现在有了一个工厂方法。现在我们只需要调用 newHashMap(size),传递所需的容量就好了。
八、日期和时间 API(Java19新增)
Date and Time API 的一个很好的增加功能是 DateTimeFormatter 的本地化支持ofLocalizedPattern() 工厂方法,传递一个字符串格式,它会生成一个本地化的模式。
DateTimeFormatterBuilder 也已更新,添加了一个 appendLocalized() 方法,用于添加一个本地化模式(类型为字符串)。
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedPattern("yM");
System.out.println(now.format(formatter)); // 2023年9月
九、IO流
PrintStream 在 Java18 中新增了 charset()方法用于获取使用的字符集。
public Charset charset();
HttpClient、ExecutorService 和 ForkJoinPool 类在 17 和 21 之间实现了 AutoCloseable。现在可以使用 try-with-resources语句来创建实例。
十、Math 和 BigInteger
Math 类和 BigInteger 类也得到了一些关注。首先,Math类添加了一系列方法。
// 执行两个数字的向上取整除法运算,并返回大于或等于除法结果的最小整数。
public static int ceilDiv(int x, int y);
public static long ceilDiv(long x, int y);
public static long ceilDiv(long x, long y);// 执行两个数字的向上取整除法运算,但是在被除数不能被除数整除时,
// 会抛出ArithmeticException异常。
public static int ceilDivExact(int x, int y);
public static long ceilDivExact(long x, long y);// 这个方法返回的是两个数字进行向上取整除法运算后的余数。
public static int ceilMod(int x, int y);
public static int ceilMod(long x, int y);
public static long ceilMod(long x, long y);// 这个方法用于对两个数字进行整除运算,并确保结果是一个整数。
// 如果除数无法整除被除数,将会抛出ArithmeticException异常。
public static int divideExact(int x, int y);
public static long divideExact(long x, long y);// 执行两个数字的向下取整除法运算,但是在被除数不能被除数整除时,
// 会抛出ArithmeticException异常。
public static int floorDivExact(int x, int y);
public static long floorDivExact(long x, long y);
添加了 clamp() 方法可以处理 int、long、float 和 double 原始类型,将提供的值限制在给定的最小值和最大值之间。
public static int clamp(long value, int min, int max);
public static long clamp(long value, long min, long max);
public static double clamp(double value, double min, double max);
public static float clamp(float value, float min, float max);
还有一个方法:unsignedMultiplyHigh(),用于将两个长整型数作为无符号数相乘,并将64位高位作为长整型返回。
public static long unsignedMultiplyHigh(long x, long y);
BigInteger 类增加了一个功能:在并行中执行乘法运算,使用了 Fork/Join 框架。
public BigInteger parallelMultiply(BigInteger val);
十一、Thread
关于 VirtualThread 的内容这里不做过多介绍,想必各位会在各种途径看到各式各样的文章。在这里,我只想介绍两个方面。
首先,Thread 现在添加了 join()方法和 sleep()方法,两者都接受 Duration 作为参数,Duration 语义化更加易用。另外就是 isVirtual()方法,用于判断线程是否为虚拟线程。
public static void sleep(Duration duration) throws InterruptedException;
public final boolean join(Duration duration) throws InterruptedException;
public final boolean isVirtual();
另外需要重点介绍的一个是在 Future 接口中添加的新方法。实际上有三个方法:
resultNow()和exceptionNow() 这两个方法不会抛出已检查异常,因此代码中不再需要 try catch,使用起来更加方便。但请注意,如果调用这些方法并且使用的 Future 对象尚未完成,那么将会得到一个 IllegalStateException异常。需要在确保 Future 对象产生了结果或异常时调用这些方法。
第三个方法是 state(),可以调用它来检查 Future 对象的当前状态。返回值是一个新的枚举:Future.State。
enum State {/*** 表示任务尚未完成*/RUNNING,/*** 表示任务成功完成*/SUCCESS,/*** 表示任务完成但出现异常*/FAILED,/*** 表示任务被取消。*/CANCELLED
}
因此,通过这个API,现在可以更精确地监控任务的进展情况。
相关文章:
Java21 LTS版本
一、前言 除了众所周知的 JEP 之外,Java 21 还有更多内容。首先请确认 java 版本: $ java -version openjdk version "21" 2023-09-19 OpenJDK Runtime Environment (build 2135-2513) OpenJDK 64-Bit Server VM (build 2135-2513, mixed mo…...
【性能优化】虚拟懒加载(下拉滚动加载长列表)element-puls+el-table
目录 前言一、卡顿的原因?二、解决1、滚动懒加载2.官方 总结 前言 提示:这里可以添加本文要记录的大概内容: 在element-plus中,如果数据超过1k,就会感觉到明显的卡顿,应该是渲染的卡顿吧。反正我在请求回…...
一对多映射处理
8.3.1 、collection /** * 根据部门id查新部门以及部门中的员工信息 * param did * return */ Dept getDeptEmpByDid(Param("did") int did);<resultMap id"deptEmpMap" type"Dept"> <id property"did" column"did&quo…...
关于IDEA没有显示日志输出?IDEA控制台没有显示Tomcat Localhost Log和Catalina Log 怎么办?
问题描述: 原因是;CATALINA_BASE里面没有相关的文件配置。而之前学习IDEA的时候,把这个文件的位置改变了。导致,最后输出IDEA的时候,不会把日志也打印出来。 检查IDEA配置; D:\work_soft\tomcat_user\Tomcat10.0\bin 在此目录下&…...
蛇形填数 rust解法
蛇形填数。 在nn方阵里填入1,2,…,nn,要求填成蛇形。例如,n=4时方阵为: 10 11 12 1 9 16 13 2 8 15 14 3 7 6 5 4 解法如下: use std::io;fn main() {let mut buf String::new();…...
一文探索SD-WAN技术进阶后与MPLS的区别
在网络通信领域,随着云计算和大数据等新兴技术的快速发展,企业对于网络的可靠性、安全性以及带宽的需求越来越高。 SD-WAN(软件定义广域网)和MPLS(多协议标签交换)是两种不同的网络连接技术,它们…...
RocketMq(四)消息分类
一、普通消息 1、同步发送消息:指的是Producer发出⼀条消息后,会在收到MQ返回的ACK之后才发下⼀条消息。该方式的消息可靠性最高,但消息发送效率低。 二、顺序消息 三、延时消息...
ip地址怎么改网速快
在当今高度依赖互联网的时代,快速稳定的网络连接对于人们的生活和工作至关重要。然而,有时我们可能会遇到网络速度缓慢的问题。虽然更改IP地址并不能直接影响网络速度,但它可以成为改善网络连接的一种策略之一。虎观代理小二二将探讨如何通过…...
植物大战僵尸各种僵尸攻略(四)
前言 此文章为“植物大战僵尸”专栏中的011刊(2023年9月第十刊),欢迎订阅。版权所有。 注意: 1.本博客适用于pvz无名版; 2.pvz指植物大战僵尸(Plants VS Zonbies); 3.本文以耗费低做标准&am…...
main函数中两个参数的作用
一般我们在使用C语言时不太用到main函数自带的参数,因此最常见的main函数就像下面这样。 int main() {...... }上面这种main函数是省略了其形参的,C语言中规定main函数的参数只能有两个,习惯上这两个参数写为argc和argv,其中&…...
华为OD机试 - 连续字母长度 - 字符串(Java 2023 B卷 100分)
目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明4、再输入5、输出6、说明 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(…...
想要精通算法和SQL的成长之路 - 填充书架
想要精通算法和SQL的成长之路 - 填充书架 前言一. 填充书架1.1 优化 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 填充书架 原题链接 题目中有一个值得注意的点就是: 需要按照书本顺序摆放。每一层当中,只要厚度不够了,当前层最高…...
【ROS入门】ROS的核心概念
文章结构 通信机制节点(Node)——执行单元节点管理器(ROS Master)——控制中心话题通信——异步通信机制话题(Topic)消息(Message)——话题数据 服务通信——同步通信机制服务(Service) 话题和服务的区别参数(Parameter)——全局共享字典 文件系统功能包(Package&am…...
Python爬虫从端到端抓取网页
网页抓取和 REST API 简介 网页抓取是使用计算机程序以自动方式从网站提取和解析数据的过程。这是创建用于研究和学习的数据集的有用技术。虽然网页抓取通常涉及解析和处理 HTML 文档,但某些平台还提供 REST API 来以机器可读格式(如 JSON)检…...
这10款类似Stable Diffusion的ai绘图软件,你了解多少?
Stable Diffusion这款ai软件有哪些可以替代的软件?好用的类似Stable Diffusion的ai软件推荐,那么今天就跟着赞奇云工作站小编一起来看看吧。 什么是Stable Diffusion? 称为“Stable Diffusion”的文本到图像模型可以将任何文本转换为逼真、…...
部署ik分词器
部署ik分词器 案例版本:elasticsearch-analysis-ik-8.6.2 ES默认自带的分词器对中文处理不够友好,创建倒排索引时可能达不到我们想要的结果,然而IK分词器能够很好的支持中文分词 因为是集群部署,所以每台服务器中的ES都需…...
基于STM32+华为云IOT设计的智能垃圾桶
一、项目介绍 在商业街、小吃街和景区等人流密集的场所,垃圾桶的及时清理对于提供良好的游客体验至关重要。然而,传统的垃圾桶清理方式通常是定时或定期进行,无法根据实际情况进行及时响应,导致垃圾桶溢满,影响环境卫…...
板子接线图
1.ST-LINK V2接线 2.对抗板子刷蓝牙固件 接USB转TTL,用镊子短接两个孔 2.对抗板子用串口测试蓝牙AT命令 短接白色箭头,接TX,RX,电源...
Python练习之选择与循环
目录 1、编写程序,运行后用户输入4位整数作为年份,判断其是否为闰年。提示:如果年份能被400整除,则为闰年;如果年份能被4整除但不能被100整除也为闰年。2、编写程序,用户从键盘输入小于 1000 的整数&#x…...
MySQL5.7开启通用日志功能
起因: 因项目数据库占用异常,查询数据库有哪些IP地址连接使用(Windows环境下)。 操作步骤: 1、修改MySQL服务的my.ini 文件 # 开启通用查询日志 general_log 1 log_output …...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
未授权访问事件频发,我们应当如何应对?
在当下,数据已成为企业和组织的核心资产,是推动业务发展、决策制定以及创新的关键驱动力。然而,未授权访问这一隐匿的安全威胁,正如同高悬的达摩克利斯之剑,时刻威胁着数据的安全,一旦触发,便可…...
