Java Matcher.reset 方法
上次修改时间:2025 年 4 月 20 日
java.util.regex.Matcher.reset 方法重置匹配器的状态。这允许使用新的输入或从头开始重新匹配来重用相同的匹配器。 该方法对于 Java 中的高效正则表达式处理至关重要。
Matcher 对象在匹配操作期间维护内部状态。reset 方法清除此状态,使匹配器准备好进行新操作。 它可以选择接受一个新的输入字符序列来匹配。
Matcher 类概述
Matcher 类解释模式并对输入字符串执行匹配操作。 它通过调用 Pattern 对象的 matcher 方法创建。 Matcher 提供了用于查找、匹配和替换的方法。
Matcher 维护有关当前匹配位置和组信息的状态。 reset 方法清除此状态,允许重用匹配器。 这比创建新的 Matcher 实例更有效。
基本重置用法
最简单的重置形式是在不更改输入的情况下清除匹配器的状态。 这允许从头开始重新匹配相同的输入。 该方法返回匹配器本身用于方法链。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetBasic {
public static void main(String[] args) {
String input = "apple orange apple banana";
Pattern pattern = Pattern.compile("apple");
Matcher matcher = pattern.matcher(input);
// First match
System.out.println("First match:");
if (matcher.find()) {
System.out.println("Found at: " + matcher.start());
}
// Reset and match again
matcher.reset();
System.out.println("\nAfter reset:");
while (matcher.find()) {
System.out.println("Found at: " + matcher.start());
}
}
}
此示例演示了基本的重置功能。 我们首先找到一个匹配项,然后重置匹配器以查找所有匹配项。 如果没有重置,第二个循环将从第一个匹配结束的地方开始。
输出显示输入字符串中“apple”的两个匹配项。 重置允许我们从输入序列的开头重新开始匹配。
使用新输入重置
reset 方法可以接受一个新的 CharSequence 输入参数。 这会更改输入文本,同时保留相同的模式。 匹配器被重置到新输入的开头。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetNewInput {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("123 456");
// Match first input
System.out.println("First input matches:");
while (matcher.find()) {
System.out.println(matcher.group());
}
// Reset with new input
matcher.reset("789 101112");
System.out.println("\nSecond input matches:");
while (matcher.find()) {
System.out.println(matcher.group());
}
}
}
此示例展示了如何使用不同的输入文本重用匹配器。 我们使用一个输入创建一个匹配器,然后使用另一个输入重置它。 相同的模式应用于两个输入。
使用新输入重置比创建新的匹配器更有效。 它重用了编译后的模式和匹配器基础设施。
在循环处理中重置
当使用相同的模式处理多个输入时,重置有助于避免创建新的匹配器。 这在对性能敏感的代码或处理大量输入时特别有用。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetLoop {
public static void main(String[] args) {
String[] inputs = {
"John: 30", "Alice: 25", "Bob: 40", "invalid entry"
};
Pattern pattern = Pattern.compile("(\\w+): (\\d+)");
Matcher matcher = pattern.matcher("");
for (String input : inputs) {
matcher.reset(input);
if (matcher.matches()) {
System.out.printf("Name: %s, Age: %s%n",
matcher.group(1), matcher.group(2));
} else {
System.out.println("Invalid format: " + input);
}
}
}
}
此示例使用单个匹配器实例处理字符串数组。 对于每个输入,我们使用新字符串重置匹配器。 这避免了为每个输入创建新匹配器的开销。
该模式从格式正确的字符串中提取名称和年龄。 无效格式将被单独检测和报告。
使用组信息重置
reset 方法清除所有匹配状态,包括组信息。 重置后,与组相关的方法将抛出 IllegalStateException,直到执行新的匹配操作。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetGroups {
public static void main(String[] args) {
String input = "Date: 2023-04-20";
Pattern pattern = Pattern.compile("Date: (\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
System.out.println("Year: " + matcher.group(1));
System.out.println("Month: " + matcher.group(2));
System.out.println("Day: " + matcher.group(3));
}
matcher.reset();
try {
// This will throw IllegalStateException
System.out.println("After reset: " + matcher.group(1));
} catch (IllegalStateException e) {
System.out.println("\nExpected exception: " + e.getMessage());
}
}
}
此示例演示了重置如何影响组信息。 在成功匹配后,我们可以访问捕获的组。 重置后,尝试访问组将抛出异常,直到我们执行另一次匹配。
发生异常的原因是组信息仅在成功匹配操作之后才有效。 重置会清除此缓存信息。
重置与新匹配器
虽然重置允许重用匹配器,但有时创建新的匹配器会更清晰。 此示例比较了两种方法在性能和内存使用方面的差异。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetVsNew {
public static void main(String[] args) {
String[] inputs = new String[1000];
for (int i = 0; i < inputs.length; i++) {
inputs[i] = "input" + i + " value" + i;
}
Pattern pattern = Pattern.compile("input(\\d+) value\\1");
// Approach 1: Reset and reuse
long start = System.nanoTime();
Matcher matcher = pattern.matcher("");
for (String input : inputs) {
matcher.reset(input);
matcher.matches();
}
long resetTime = System.nanoTime() - start;
// Approach 2: New matcher each time
start = System.nanoTime();
for (String input : inputs) {
Matcher m = pattern.matcher(input);
m.matches();
}
long newTime = System.nanoTime() - start;
System.out.printf("Reset approach: %,d ns%n", resetTime);
System.out.printf("New matcher approach: %,d ns%n", newTime);
}
}
此基准测试比较了重置匹配器与创建新匹配器。 在大多数情况下,重置略快,因为它避免了对象分配。 然而,对于许多应用程序来说,这种差异可能可以忽略不计。
两种方法之间的选择取决于代码清晰度要求和性能需求。 对于关键循环,重置可以提供更好的性能。
使用区域更改重置
reset 方法还会清除应用于匹配器的任何区域设置。 重置后,匹配器将再次对整个输入序列进行操作。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetRegion {
public static void main(String[] args) {
String input = "123-456-789";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(input);
// Set region to match only the middle part
matcher.region(4, 7);
System.out.println("Matches in region:");
while (matcher.find()) {
System.out.println(matcher.group());
}
// Reset clears region settings
matcher.reset();
System.out.println("\nMatches after reset:");
while (matcher.find()) {
System.out.println(matcher.group());
}
}
}
此示例展示了重置如何影响区域设置。 我们首先将匹配限制为子字符串区域,然后重置以再次匹配整个输入。
重置将匹配器恢复到其默认状态,其中区域包含整个输入序列。 将删除所有特定于区域的限制。
在多线程环境中重置
虽然 Matcher 实例不是线程安全的,但重置可以帮助在受控的多线程场景中安全地重用匹配器。 每个线程都应该有自己的匹配器实例。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherResetThreads {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\b\\w{4}\\b");
String[] inputs = {
"This is a test string",
"Four word length test",
"Another example input"
};
for (String input : inputs) {
new Thread(() -> {
Matcher matcher = pattern.matcher("");
matcher.reset(input);
System.out.println(Thread.currentThread().getName() + ":");
while (matcher.find()) {
System.out.println(" " + matcher.group());
}
}).start();
}
}
}
此示例演示了线程安全的匹配器用法。 每个线程创建并重置其自己的匹配器实例。 该模式被安全地共享,因为它是不变的。
输出显示每个线程独立处理其输入。 重置允许重用匹配器,同时通过适当的实例隔离来保持线程安全。
来源
在本文中,我们深入探讨了 Matcher.reset 方法。 我们介绍了它的基本用法、性能影响和线程安全注意事项。 了解重置是 Java 中高效正则表达式处理的关键。
作者
列出所有Java教程。