不要对正则表达式进行频繁重复预编译
背景
在频繁调用场景,如方法体内或者循环语句中,新定义Pattern会导致重复预编译正则表达式,降低程序执行效率。另外,在 JDK 中部分 入参为正则表达式格式的 API,如 String.replaceAll
, String.split
等,也需要关注性能问题。
验证
正例:
将 Pattern 对象预编译,并在常量中声明。
private static final String IP_V4 = "^(((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))$";// Pattern 常量private static final Pattern IP_V4_PATTERN = Pattern.compile(IP_V4);public static boolean isValidIpv4V2(String input) {if (input == null) {return false;}return IP_V4_PATTERN.matcher(input).matches();}
反例:
每次调用时才声明 Pattern。
private static final String IP_V4 = "^(((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))$";public static boolean isValidIpv4V1(String input) {if (input == null) {return false;}Pattern pattern = Pattern.compile(IP_V4);return pattern.matcher(input).matches();}
测试代码:
package com.ysx.utils.pattern.performance;import org.junit.jupiter.api.Test;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;/*** @author youngbear* @email youngbear@aliyun.com* @date 2023-09-17 8:31* @blog <a href="https://blog.csdn.net/next_second">...</a>* @github <a href="https://github.com/YoungBear">...</a>* @description 正则表达式性能测试*/
public class PrecompilePerformanceTest {private static final String IP_V4 = "^(((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))$";// Pattern 常量private static final Pattern IP_V4_PATTERN = Pattern.compile(IP_V4);// 缓存private static final Map<String, Pattern> cacheCompilePatternMap = new ConcurrentHashMap<>();public static boolean isValidIpv4V1(String input) {if (input == null) {return false;}Pattern pattern = Pattern.compile(IP_V4);return pattern.matcher(input).matches();}public static boolean isValidIpv4V2(String input) {if (input == null) {return false;}return IP_V4_PATTERN.matcher(input).matches();}public static boolean isValidIpv4V3(String input) {if (input == null) {return false;}if (!cacheCompilePatternMap.containsKey(IP_V4)) {cacheCompilePatternMap.put(IP_V4, Pattern.compile(IP_V4));}Pattern pattern = cacheCompilePatternMap.get(IP_V4);return pattern.matcher(input).matches();}@Testpublic void performanceTest() {String input1 = "192.168.12.13";long start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {isValidIpv4V1(input1);}long stop = System.currentTimeMillis();System.out.println("isValidIpv4V1, input1, consume: " + (stop - start) + "ms");String input2 = "192.168.12.13";long start2 = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {isValidIpv4V1(input2);}long stop2 = System.currentTimeMillis();System.out.println("isValidIpv4V1, input2, consume: " + (stop2 - start2) + "ms");}@Testpublic void performanceV2Test() {String input1 = "192.168.12.13";long start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {isValidIpv4V2(input1);}long stop = System.currentTimeMillis();System.out.println("isValidIpv4V2, input1, consume: " + (stop - start) + "ms");String input2 = "192.168.12.13";long start2 = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {isValidIpv4V2(input2);}long stop2 = System.currentTimeMillis();System.out.println("isValidIpv4V2, input2, consume: " + (stop2 - start2) + "ms");}@Testpublic void performanceV3Test() {String input1 = "192.168.12.13";long start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {isValidIpv4V3(input1);}long stop = System.currentTimeMillis();System.out.println("isValidIpv4V3, input1, consume: " + (stop - start) + "ms");String input2 = "192.168.12.13";long start2 = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {isValidIpv4V3(input2);}long stop2 = System.currentTimeMillis();System.out.println("isValidIpv4V3, input2, consume: " + (stop2 - start2) + "ms");}}
执行结果:
isValidIpv4V1, input1, consume: 232ms
isValidIpv4V1, input2, consume: 74ms
isValidIpv4V2, input1, consume: 24ms
isValidIpv4V2, input2, consume: 19ms
isValidIpv4V3, input1, consume: 20ms
isValidIpv4V3, input2, consume: 12ms
根据执行结果,可以明显看到,预编译正则表达式可以提升性能。
总结
- 通常情况下,正则表达式为常量,所以可以将其作为常量量,在类编译时预编译。
private static final Pattern xxx_PATTERN = Pattern.compile("xxx");
- 对于动态的正则表达式,可以将其缓存,即缓存其 Pattern 结果。(参考
isValidIpv4V3
)。 - 另外,对于外部收入的正则表达式,一定要校验其安全性,防止 ReDos 攻击。
相关文章:
不要对正则表达式进行频繁重复预编译
背景 在频繁调用场景,如方法体内或者循环语句中,新定义Pattern会导致重复预编译正则表达式,降低程序执行效率。另外,在 JDK 中部分 入参为正则表达式格式的 API,如 String.replaceAll, String.split 等,也…...
vue入门及小项目小便签条
vue 框架:是一个半成品软件,是一套可重用的,通用的,软件基础代码模型。基于框架进行开发,更加快捷 ,更加高效 v-bind为HTML标签绑定属性值,如设置href,css样式等 v-model在表单元素上创建双向数…...

详解TCP/IP协议第四篇:数据在网络中传输方式的分类概述
文章目录 前言 一:面向有连接型与面向无连接型 1:大致概念 2:面向有连接型 3:面向无连接型 二:电路交换与分组交换 1:分组交换概念 2:分组交交换过程 三:根据接收端数量分…...

SpringMvc决战-【SpringMVC之自定义注解】
目录 一、前言 1.1.什么是注解 1.2.注解的用处 1.3.注解的原理 二.注解父类 1.注解包括那些 2.JDK基本注解 3. JDK元注解 4.自定义注解 5.如何使用自定义注解(包括:注解标记【没有任何东西】,元数据注解)? 三…...

【MySQL集群一】CentOS 7上搭建MySQL集群:一主一从、多主多从
CentOS 7上搭建MySQL集群 介绍一主一从步骤1:准备工作步骤2:安装MySQL步骤3:配置主服务器步骤4:创建复制用户步骤5:备份主服务器数据,如果没有数据则省略这一步步骤6:配置从服务器步骤7…...

RGB格式
Qt视频播放器实现(目录) RGB的使用场景 目前,数字信号源(直播现场的数字相机采集的原始画面)和显示设备(手机屏幕、笔记本屏幕、个人电脑显示器屏幕)使用的基本上都是RGB格式。 三原色 RGB是…...

认识面向对象-PHP8知识详解
面向对象编程,也叫面向对象程序设计,是在面向过程程序设计的基础上发展而来的,它比面向过程编程具有更强的灵活性和扩展性。 它用类、对象、关系、属性等一系列东西来提高编程的效率,其主要的特性是可封装性、可继承性和多态性。…...

毕业设计|基于51单片机的空气质量检测PM2.5粉尘检测温度设计
基于51单片机的空气质量检测PM2.5粉尘检测温度设计 1、项目简介1.1 系统构成1.2 系统功能 2、部分电路设计2.1 LED信号指示灯电路设计2.2 LCD1602显示电路2.3 PM2.5粉尘检测电路设计 3、部分代码展示3.1 串口初始化3.1 定时器初始化3.2 LCD1602显示函数 4 演示视频及代码资料获…...

星闪空口技术初探
星闪技术设计目标 在星闪技术的应用场景中,最低的时延要求达到了20us量级,比如智能座舱的主动降噪。最高的可靠性要求达到了99.9999%,比如智能制造的传感器与执行器的消息收发。除了低时延和高可靠之外,高精度同步、多并发和信息…...

如何在不失去理智的情况下调试 TensorFlow 训练程序
一、说明 关于tensorflow的调试,是一个难啃的骨头,除了要有耐力,还需要方法;本文假设您是一个很有耐力的开发者,为您提供一些方法;这些方法也许不容易驾驭,但是依然强调您只要有耐力,…...

24. 图论 - 图的表示种类
Hi,你好。我是茶桁。 之前的一节课中,我们了解了图的来由和构成,简单的理解了一下图的一些相关概念。那么这节课,我们要了解一下图的表示,种类。相应的,我们中间需要穿插一些新的知识点用于更好的去理解图…...
C++ 读bin文件,部分代码。赚经验。
编号:1 Head: magicWord[0] 0x0102 magicWord[1] 0x0304 magicWord[2] 0x0506 magicWord[3] 0x0708 version 0x02010004 totalPacketLen 288 platform 0x000a1443 frameNumber 12 timeCpuCycles 172969774 numDetectedObj 99 numTLVs 2 subFrameNumber 0 TLV…...
vue3 父子组件传值
一,子传父 父组件 <script setup> import HelloWorld from ./components/HelloWorld.vue import { ref } from vue//直接赋值页面不会自动渲染,使用ref存储响应式数据 import { defineExpose } from "vue";父传子 let val ref(); con…...

【看懂MPLS LSP表项】
IP网络 R1根据路由表项去查FIB表 目的网络、出口、下一跳 MPLS网络 R1根据LFIB表现去查表, 路由,出口、(标签) 要实现MPLS网络全局可达性,R1应具有到每一个LSR、LSE的路由。 1、R1去FEC(转发等价类) /去往2.2.2.2的路由《路由方…...
代码随想录训练营 单调栈
代码随想录训练营 单调栈 84. 柱状图中最大的矩形🌸 最后一天~ 84. 柱状图中最大的矩形🌸 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最…...
Android MQTT
MQTT Android MQTT连接,重新编译Service-1.1.1兼容Android高版本服务 Paho Android Service-1.1.1 Paho Client Mqtt3-1.1.0 资源 名字资源AAR下载GitHub查看Gitee查看 Maven 1.build.grade allprojects {repositories {...maven { url https://jitpack.io }} }2./app/bu…...
Codeforces Round 823 (Div. 2)C
更好的阅读体验 C. Minimum Notation 思路:我们可以进行的操作时将一个位置的数删除然后在任意位置处添加一个比当前数大1并且小于9的数,所以我们的操作只会让一个数变大,我们统计一个最大值的后缀,贪心的考虑如果当前数的后面有…...

npm发布vue3自定义组件库--方法一
npm发布vue3自定义组件库 创建项目 vue create test-ui自定义组件 创建自定义组件,组件名称根据你的需求来,最好一个组件一个文件夹,下图是我的示例。 src/components 组件和你写页面一样,所谓组件就是方便实用,不…...

Centos7原生hadoop环境,搭建Impala集群和负载均衡配置
Centos7原生hadoop环境,搭建Impala集群和负载均衡配置 impala介绍 Impala集群包含一个Catalog Server (Catalogd)、一个Statestore Server (Statestored) 和若干个Impala Daemon (Impalad)。Catalogd主要负责元数据的获取和DDL的执行,Statestored主要负…...
如何在macOS上安装Go并搭建本地编程环境
引言 Go是一种诞生于挫折中的编程语言。在谷歌,开发人员厌倦了在为新项目选择语言时必须做出权衡。有些语言执行效率很高,但需要很长时间编译,而另一些语言易于编写,但在生产环境中运行效率很低。因此,谷歌发明了Go语…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...