在Java中,正则表达式是一种强大的文本处理工具,它允许开发者通过特定的模式匹配、查找、替换或分割字符串,Java对正则表达式的支持主要来自java.util.regex包,该包包含两个核心类:Pattern和Matcher,掌握这两个类的使用方法,以及正则表达式的基本语法,是高效处理文本数据的关键。

正则表达式基础语法
正则表达式由普通字符和特殊字符(元字符)组成,普通字符如字母、数字等会直接匹配自身,而元字符则具有特殊的匹配含义,常见的元字符包括:
- 匹配除换行符外的任意单个字符。
- 匹配前面的元素零次或多次。
- 匹配前面的元素一次或多次。
- 匹配前面的元素零次或一次。
{n}:匹配前面的元素恰好n次。{n,}:匹配前面的元素至少n次。{n,m}:匹配前面的元素至少n次,但不超过m次。[]:字符类,匹配方括号内的任意一个字符,例如[abc]匹配a、b或c。[^]:否定字符类,匹配不在方括号内的任意字符,例如[^abc]匹配除a、b、c外的任意字符。- 选择符,匹配其左右两边的任意一个表达式,例如
a|b匹配a或b。 - 分组,将括号内的表达式作为一个整体,例如
(ab)+匹配ab、abab等。 \d:匹配任意数字字符,等同于[0-9]。\D:匹配任意非数字字符,等同于[^0-9]。\w:匹配任意单词字符(字母、数字、下划线),等同于[a-zA-Z0-9_]。\W:匹配任意非单词字符。\s:匹配任意空白字符(空格、制表符、换行符等)。\S:匹配任意非空白字符。^:匹配字符串的开始。- 匹配字符串的结束。
Pattern与Matcher类的使用
Pattern类是正则表达式的编译表示,通过Pattern.compile()方法可以将正则表达式字符串编译成一个Pattern对象。
Pattern pattern = Pattern.compile("\\d+");
需要注意的是,在Java字符串中,反斜杠\是转义字符,因此正则表达式中的\d需要写成\\d。
Matcher类是对输入字符串进行解释和匹配操作的引擎,通过Pattern对象的matcher()方法可以创建一个Matcher对象。
Matcher matcher = pattern.matcher("abc123def456");
Matcher类提供了多种方法进行匹配操作:

matches():尝试将整个输入序列与模式匹配,返回布尔值。lookingAt():尝试从输入序列的开头开始匹配模式,返回布尔值。find():扫描输入序列,查找与模式匹配的子序列,返回布尔值。group():返回最近一次匹配的子序列。start()和end():返回最近一次匹配的子序列在输入序列中的开始和结束索引。
实际应用示例
检查字符串是否匹配正则表达式
假设要检查一个字符串是否是一个有效的手机号码(假设手机号码为11位数字):
String phone = "13812345678";
Pattern pattern = Pattern.compile("^\\d{11}$");
Matcher matcher = pattern.matcher(phone);
boolean isValid = matcher.matches();
System.out.println("手机号码是否有效: " + isValid); // 输出: true
查找所有匹配的子序列
从一个字符串中提取所有数字:
String text = "价格100元,数量50件,总价5000元";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println("找到数字: " + matcher.group());
}
// 输出:
// 找到数字: 100
// 找到数字: 50
// 找到数字: 5000
替换匹配的子序列
将字符串中的所有数字替换为[NUMBER]:
String text = "订单号12345,金额678.9元";
Pattern pattern = Pattern.compile("\\d+(\\.\\d+)?");
Matcher matcher = pattern.matcher(text);
String result = matcher.replaceAll("[NUMBER]");
System.out.println(result); // 输出: 订单号[NUMBER],金额[NUMBER]元
分割字符串
使用正则表达式分割字符串:
String text = "apple,banana;orange|grape";
String[] fruits = text.split("[,;|]");
for (String fruit : fruits) {
System.out.println(fruit);
}
// 输出:
// apple
// banana
// orange
// grape
高级特性
捕获组与非捕获组
正则表达式中的括号不仅可以分组,还可以捕获匹配的子序列,通过group()方法可以访问这些捕获组。

String text = "2023-10-01";
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("年份: " + matcher.group(1)); // 输出: 2023
System.out.println("月份: " + matcher.group(2)); // 输出: 10
System.out.println("日期: " + matcher.group(3)); // 输出: 01
}
如果不需要捕获分组,可以使用非捕获组,这样可以提高匹配效率并减少内存消耗。
预查与负预查
预查(lookaround)是一种零宽断言,它只匹配位置而不消耗字符,正向预查表示后面必须跟着指定的模式,负向预查表示后面不能跟着指定的模式。
String text = "Java8, Java11, Java17";
Pattern pattern = Pattern.compile("Java(?=\\d+)"); // 匹配后面跟着数字的Java
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group()); // 输出: Java, Java, Java
}
性能优化建议
在使用正则表达式时,需要注意性能问题:
- 预编译正则表达式:如果同一个正则表达式会被多次使用,应使用
Pattern.compile()预先编译,避免重复编译带来的性能开销。 - 避免贪婪匹配:默认情况下,量词(如、、)是贪婪的,会匹配尽可能多的字符,如果需要最小匹配,可以使用惰性量词(如、、)。
- 简化正则表达式:复杂的正则表达式可能难以理解和维护,也影响性能,尽量使用简洁的模式。
- 避免回溯:某些正则表达式可能导致大量的回溯,从而降低性能,可以通过使用原子组或占有量词(如、)来减少回溯。
正则表达式是Java文本处理的利器,通过Pattern和Matcher类,可以实现复杂的字符串匹配、查找、替换和分割操作,掌握正则表达式的基本语法、核心类的使用方法以及高级特性,能够帮助开发者更高效地处理文本数据,在实际应用中,需要注意性能优化,选择合适的正则表达式模式,以达到最佳的处理效果。

















