正则表达式的基础概念
正则表达式(Regular Expression,简称Regex)是一种用于描述字符串模式的强大工具,在Java中,正则表达式主要通过java.util.regex包中的Pattern和Matcher类来实现,它能够高效地进行字符串的匹配、查找、替换和分割等操作,广泛应用于数据验证、文本处理、日志解析等场景,掌握Java正则表达式的使用方法,能够显著提升开发效率和代码质量。

核心类与方法
Java正则表达式的核心是Pattern和Matcher两个类。Pattern类用于编译正则表达式,生成一个Pattern对象;Matcher类则负责对输入字符串进行匹配操作。String类也提供了一些便捷方法,如matches()、replaceAll()等,它们内部也依赖于Pattern和Matcher实现。
编译正则表达式
使用Pattern.compile()方法可以将正则表达式字符串编译为一个Pattern对象。
Pattern pattern = Pattern.compile("\\d+"); // 匹配一个或多个数字
编译后的Pattern对象可以被重复使用,提高性能。
创建匹配器
通过Pattern对象的matcher()方法可以创建一个Matcher对象,用于对具体字符串进行匹配:
Matcher matcher = pattern.matcher("abc123def");
常用匹配方法
matches():整个字符串是否匹配正则表达式。lookingAt():字符串开头是否匹配正则表达式。find():字符串中是否存在匹配的子串。group():获取匹配到的子串。
基本语法与元字符
正则表达式由普通字符和元字符组成,元字符是具有特殊含义的字符,用于定义匹配模式,以下是常用的元字符及其含义:

字符类
- 匹配任意字符(除换行符外)。
[abc]:匹配字符a、b或c。[^abc]:匹配除a、b、c之外的任意字符。[a-z]:匹配a到z之间的任意小写字母。[A-Z]:匹配A到Z之间的任意大写字母。[0-9]:匹配任意数字,等同于\d。\D:匹配非数字字符。\w:匹配单词字符(字母、数字、下划线)。\W:匹配非单词字符。\s:匹配空白字符(空格、制表符、换行符等)。\S:匹配非空白字符。
量词
- 匹配前面的元素零次或多次。
- 匹配前面的元素一次或多次。
- 匹配前面的元素零次或一次。
{n}:匹配前面的元素恰好n次。{n,}:匹配前面的元素至少n次。{n,m}:匹配前面的元素至少n次,最多m次。
定位符
^:匹配字符串开头。- 匹配字符串结尾。
\b:匹配单词边界。\B:匹配非单词边界。
分组与引用
- 分组,可以捕获匹配的子串。
\1、\2等:引用分组中的内容。(\d)\1匹配两个连续的相同数字。
实际应用示例
字符串验证
验证邮箱格式是否正确:
String email = "example@domain.com";
boolean isValid = email.matches("^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$");
System.out.println(isValid); // 输出true
提取子串
从字符串中提取所有手机号码(假设手机号码为11位数字):
String text = "我的手机号是13812345678,备用号是15987654321。";
Pattern pattern = Pattern.compile("1[3-9]\\d{9}");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println("找到手机号:" + matcher.group());
}
将字符串中的所有空格替换为下划线:
String str = "This is a test string.";
String result = str.replaceAll("\\s", "_");
System.out.println(result); // 输出This_is_a_test_string_
分割字符串
按多个分隔符(如逗号、分号、空格)分割字符串:
String str = "apple,banana;orange grape";
String[] fruits = str.split("[,;\\s]+");
for (String fruit : fruits) {
System.out.println(fruit);
}
高级特性
贪婪模式与非贪婪模式
默认情况下,量词是贪婪的,会匹配尽可能多的字符,在量词后加上可以切换为非贪婪模式。

String str = "<div>内容</div>";
Pattern pattern = Pattern.compile("<div>.*</div>"); // 贪婪模式,匹配整个字符串
Pattern patternNonGreedy = Pattern.compile("<div>.*?</div>"); // 非贪婪模式,仅匹配<div>内容</div>
预查(零宽断言)
预查用于匹配某个位置之前或之后的内容,但不消耗字符。
(?=exp):正向预查,匹配后面跟着exp的位置。(?!exp):负向预查,匹配后面不跟着exp的位置。
示例:匹配后面跟着“com”的单词:String str = "example.com test.com"; Pattern pattern = Pattern.compile("\\w+(?=\\.com)"); Matcher matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group()); // 输出example和test }
标志(Flags)
编译正则表达式时可以添加标志,控制匹配行为。
Pattern.CASE_INSENSITIVE:忽略大小写。Pattern.MULTILINE:多行模式,^和匹配每行的开头和结尾。
示例:忽略大小写匹配“java”:Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher("Java is great."); System.out.println(matcher.find()); // 输出true
性能优化建议
- 预编译正则表达式:如果正则表达式会被多次使用,建议使用
Pattern.compile()预编译,避免重复编译的开销。 - 避免复杂回溯:复杂的正则表达式可能导致回溯次数过多,影响性能,可以通过具体化字符类、减少嵌套量词等方式优化。
- 使用非贪婪模式:在可能的情况下,使用非贪婪模式减少不必要的匹配尝试。
- 限制匹配范围:通过
Matcher.region()方法限制匹配范围,提高处理大文本时的效率。
常见错误与注意事项
- 转义字符问题:在Java字符串中,反斜杠
\需要转义为\\,匹配数字应写为\\d,而不是\d。 - 边界匹配错误:忘记使用
^和可能导致部分匹配而非完全匹配。"123".matches("\\d")返回false,因为整个字符串需要完全匹配。 - 分组捕获陷阱:未命名的分组会占用内存,如果不需要捕获分组内容,可以使用非捕获分组。
Java正则表达式是处理文本数据的利器,通过灵活运用Pattern和Matcher类,结合丰富的元字符和语法,可以实现复杂的字符串操作,从基础的字符匹配到高级的预查和性能优化,掌握正则表达式的使用技巧能够显著提升开发效率,在实际应用中,建议结合具体场景选择合适的正则表达式模式,并注意性能优化和错误处理,以确保代码的健壮性和高效性。















