善用Pattern提高你的应用处理正则表达式的效率(Java)

本文通过对比String.matches()方法和Pattern类在不同运行次数下验证邮箱格式的效率,发现使用Pattern类预编译正则表达式能有效提升性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

举个简单了例子,在一个需要用于注册登录的b/s模式的应用中,在浏览器验证用户注册表单的合法性是必须的,但你为了防止hacker,在服务器再验证一次肯定也是必须的。

题目:在服务器端验证邮箱是否合法:通常你可能会这样写:

public boolean checkEmailLegal(String temp)
{
    //temp = "ddenfj#@fe_dw.comw";
    return temp.matches("^([\\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$");
}


当然这样写可以满足你的需求,但是,今天要和大家分享我使用Pattern提高效率的使用心得,首先,先看一下我对小面代码进行的简单的测试:

import java.util.regex.Pattern;

public class SimpleTest {
	public static void main(String[] args)
	{
		String temp = "ddenfj#@fe_dw.comw";
		int count = 1;
		long a = System.currentTimeMillis();
		for(int i=0;i<count;i++)
		{
			temp.matches("^([\\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$");
		}
		long b = System.currentTimeMillis();
		System.out.println(b-a);
		a = System.currentTimeMillis();
		Pattern emailPattern = Pattern.compile("^([\\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$");
		for(int i=0;i<count;i++)
		{
			emailPattern.matcher(temp).matches();
		}
		b = System.currentTimeMillis();
		System.out.println(b-a);
	}
}
运行次数为 1 时,运行结果:

4

0

运行次数为 100 时,运行结果:

16

1

运行次数为1000时,运行结果:

111

8

运行次数为10000时,运行结果:

343

11

运行次数为100000时,运行结果:

841

65

运行次数为一千万时,运行结果:

8205

94

我们知道,匹配正则表达式首先创建有穷自动机

我的结论:从测试记过可以看出String.matches()方法的时间并不是想想中的线性增长的,可以得出的结论是jvm一定对String.matches()方法进行了缓存的处理,也就是说调用这个方法产生的一切中间对象并未被jvm清理,如果运用到你的应用上,可能效率体现得会很明显




----------------------------------------------------------------------------------------------------------

写完以上内容,还在我洋洋自得的时候,我想看一下String.matches()的源代码:

public boolean matches(String regex) {
        return Pattern.matches(regex, this);
    }


public static boolean matches(String regex, CharSequence input) {
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(input);
        return m.matches();
    }

看来我对jvm的上方理解是错误的,

不过从他们的源码我们可以看出来,如果把Pattern写成一个静态(static)属性,并用spring管理对象,那效率还是会提高很多的!

望共勉!



<think>好的,我现在需要给用户讲解正则表达式,得用通俗易懂的方式。首先,我得理解用户的需求。他们可能对编程有一定了解,但正则表达式看起来复杂,需要简化。 首先,我应该从比喻入手,比如把正则表达式比作通配符,但更强大。这样用户容易联想到已有的知识。比如,用户可能知道在文件搜索中用*代表任意字符,正则表达式类似但功能更多。 接下来,需要介绍基本概念,比如元字符。用户可能不熟悉这些术语,所以要用例子说明。比如,\d代表数字,.代表任意字符,这样具体的例子能帮助记忆。 然后,要分步骤讲解,比如先讲匹配单个字符,再讲量词、分组和选择。这样结构清晰,用户容易跟上。每个部分都要有例子,比如用电话号码和邮箱的匹配作为实例,这样实用性强。 还要注意用户的常见问题,比如贪婪模式,可能需要用简单的话解释,避免太技术化。比如,提到量词默认尽可能多匹配,而加?变成尽可能少,这样对比容易理解。 最后,给出总结和练习建议,帮助用户巩固。可能还要提醒正则表达式在不同语言中的差异,避免用户混淆。 检查是否需要遵循用户的格式要求,比如行内公式用$...$,独立公式用$$...$$。但这里讲正则表达式可能用不到数学公式,不过如果有涉及,比如讲到重复次数时用{n,m},可能需要用代码格式而非数学公式。但根据用户给的系统指令,可能不需要,所以确保用反引号包裹代码示例。 还要确保用中文,结构清晰,分点讲解,步骤化。避免使用专业术语过多,必要时解释术语。比如“元字符”需要解释为“特殊字符”。 可能还需要检查是否有错误,比如正则表达式中的转义字符是否正确,比如\.表示真正的点号,而用户可能容易忽略反斜杠的作用,需要强调。 总之,结构大致是:比喻引入 -> 基本概念 -> 组成部分分点讲解 -> 实例 -> 注意事项 -> 总结。每个部分用例子和简单语言,确保用户能逐步理解。</think>让我们用“通配符升级版”来通俗理解正则表达式: ✍️ 简单理解:正则表达式就像超级智能的**文本搜索密码**,用特定符号组合快速完成以下任务: - ✅ 检测文本规律(如判断手机号格式) - ✅ 批量提取信息(如从网页抓取所有邮箱) - ✅ 智能替换内容(如给所有数字加粗) 🔑 核心学习路径(分三步): 1. **单个字符匹配** - `\d` = 匹配任意数字(相当于`[0-9]`) - `\w` = 匹配字母/数字/下划线(相当于`[A-Za-z0-9_]`) - `.` = 匹配任意字符(除换行符) - 举例:`A\d` 可以匹配 "A3"、"A9" 2. **数量控制符** - `*` = 出现0次或多次(贪婪模式) - `+` = 出现1次或多次 - `?` = 出现0或1次(也可用于非贪婪模式) - `{2}` = 精确出现2次 - 举例:`AB+` 匹配 "AB"、"ABBB" 3. **位置与逻辑** - `^` = 字符串开头 - `$` = 字符串结尾 - `|` = 或逻辑(如`猫|狗`) - `()` = 捕获分组 - 举例:`^Hello` 只匹配开头的Hello 🛠️ 经典使用场景: ```regex 电话号匹配:^1[3-9]\d{9}$ // 匹配11位手机号 邮箱匹配:\w+@[a-z0-9]+\.[a-z]+ // 匹配简单邮箱格式 HTML标签提取:<(.*?)> // 非贪婪模式匹配标签 ``` ❗ 重要注意事项: 1. 特殊字符需转义(如匹配真正的`.`要写成`\.`) 2. 默认**贪婪匹配**(加`?`变非贪婪:`.*?`) 3. 不同编程语言实现有细微差异 🔍 学习方法建议: 1. 先用在线测试工具(如regex101.com)实时验证 2. 从简单模式开始逐步增加复杂度 3. 善用预置字符集(如`\s`匹配空白符) 通过掌握这些核心规则,您就能快速编写出匹配身份证号、URL解析、文本清洗等实用表达式啦!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值