ZetCode

Java Matcher.toMatchResult 方法

上次修改时间:2025 年 4 月 20 日

Java 中的 Matcher.toMatchResult 方法返回当前匹配状态的快照,作为 MatchResult 对象。 这允许您捕获和检查匹配信息,而不会影响匹配器的状态。

MatchResult 接口提供了访问匹配详细信息(如组内容和位置)的方法。 当您需要保留匹配信息以供以后处理或与多个线程一起工作时,这非常有用。

Matcher.toMatchResult 概述

toMatchResult 方法创建当前匹配状态的不可变快照。 返回的 MatchResult 包含有关匹配的所有信息,包括组及其位置。

当您需要存储匹配结果或将其传递给其他方法时,此方法特别有用。 即使原始匹配器继续匹配操作,快照仍然有效。

toMatchResult 的基本用法

此示例演示了 toMatchResult 的基本用法来捕获匹配信息。 我们将从一个简单的模式匹配中提取细节。

BasicMatchResult.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class BasicMatchResult {

    public static void main(String[] args) {
        String input = "The quick brown fox jumps over the lazy dog";
        String regex = "(quick) (brown) (fox)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            MatchResult result = matcher.toMatchResult();
            
            System.out.println("Full match: " + result.group());
            System.out.println("Group 1: " + result.group(1));
            System.out.println("Group 2: " + result.group(2));
            System.out.println("Group 3: " + result.group(3));
            
            System.out.println("Match start: " + result.start());
            System.out.println("Match end: " + result.end());
        }
    }
}

在此示例中,我们创建一个带有三个捕获组的模式。 找到匹配项后,我们使用 toMatchResult 来捕获匹配状态。

MatchResult 对象提供对匹配文本及其在输入字符串中的位置的访问权限。 我们可以使用 group 方法检索完整的匹配项和各个组。

多个匹配快照

此示例演示了如何在匹配操作期间捕获多个匹配状态。 我们将每个匹配结果存储在一个列表中,以供以后处理。

MultipleMatchResults.java
package com.zetcode;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class MultipleMatchResults {

    public static void main(String[] args) {
        String input = "John:30, Jane:25, Bob:40, Alice:35";
        String regex = "(\\w+):(\\d+)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        List<MatchResult> results = new ArrayList<>();
        
        while (matcher.find()) {
            results.add(matcher.toMatchResult());
        }
        
        System.out.println("Captured matches:");
        for (MatchResult result : results) {
            System.out.printf("Name: %s, Age: %s%n", 
                result.group(1), result.group(2));
        }
    }
}

在这里,我们处理包含名称-年龄对的字符串。 对于找到的每个匹配项,我们使用 toMatchResult 存储匹配状态。

存储的 MatchResult 对象允许我们稍后处理匹配项,即使在匹配器继续其操作之后也是如此。 这对于匹配结果的批处理非常有用。

线程安全的匹配结果

此示例演示了如何使用 toMatchResult 创建线程安全的匹配结果。 可以安全地将快照传递给另一个线程。

ThreadSafeMatchResult.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class ThreadSafeMatchResult {

    public static void main(String[] args) {
        String input = "Server1:192.168.1.1, Server2:192.168.1.2";
        String regex = "(Server\\d+):(\\d+\\.\\d+\\.\\d+\\.\\d+)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        while (matcher.find()) {
            MatchResult result = matcher.toMatchResult();
            
            new Thread(() -> {
                System.out.printf("Processing %s at %s in thread %s%n",
                    result.group(1), result.group(2),
                    Thread.currentThread().getName());
            }).start();
        }
    }
}

在此示例中,我们为每个匹配结果创建一个新线程。 MatchResult 快照安全地传递给每个线程。

如果没有 toMatchResult,在线程之间共享匹配器状态将是不安全的。 不可变的快照确保对匹配结果的线程安全访问。

带组的匹配结果

此示例演示了如何使用 toMatchResult 处理捕获的组。 我们将从一个复杂的模式中提取结构化数据。

GroupMatchResult.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class GroupMatchResult {

    public static void main(String[] args) {
        String input = "Date: 2023-04-20, Time: 14:30, Location: Room 101";
        String regex = "Date: (?<date>\\d{4}-\\d{2}-\\d{2}), " +
                      "Time: (?<time>\\d{2}:\\d{2}), " +
                      "Location: (?<location>[A-Za-z0-9 ]+)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            MatchResult result = matcher.toMatchResult();
            
            System.out.println("Full match: " + result.group());
            System.out.println("Date: " + result.group("date"));
            System.out.println("Time: " + result.group("time"));
            System.out.println("Location: " + result.group("location"));
            
            System.out.println("Group count: " + result.groupCount());
        }
    }
}

在这里,我们使用命名捕获组从字符串中提取结构化信息。 MatchResult 提供对编号组和命名组的访问。

该示例演示了 toMatchResult 如何保留所有组信息,使其可供以后使用。 组计数包括模式中的所有捕获组。

匹配位置信息

此示例侧重于从 MatchResult 检索匹配位置信息。 我们将检查匹配项的开始和结束位置。

PositionMatchResult.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class PositionMatchResult {

    public static void main(String[] args) {
        String input = "The rain in Spain falls mainly on the plain";
        String regex = "\\b\\w{4}\\b"; // 4-letter words
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        while (matcher.find()) {
            MatchResult result = matcher.toMatchResult();
            
            System.out.printf("Word '%s' found at [%d,%d)%n",
                result.group(),
                result.start(),
                result.end());
                
            System.out.println("Surrounding text: '" +
                input.substring(Math.max(0, result.start() - 3),
                               Math.min(input.length(), result.end() + 3)) +
                "'");
        }
    }
}

此代码查找字符串中的所有 4 个字母的单词并捕获它们的位置。 MatchResult 提供精确的位置信息。

我们使用位置数据来提取每个匹配项周围的文本。 这演示了位置信息如何对匹配项的上下文感知处理非常有用。

重用匹配结果

此示例演示了如何在程序中存储和重用匹配结果。 我们将在匹配操作完成后处理结果。

ReuseMatchResult.java
package com.zetcode;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class ReuseMatchResult {

    public static void main(String[] args) {
        String input = "Product1: $10.99, Product2: $20.50, Product3: $5.75";
        String regex = "Product(\\d+): \\$(\\d+\\.\\d{2})";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        List<MatchResult> results = new ArrayList<>();
        
        while (matcher.find()) {
            results.add(matcher.toMatchResult());
        }
        
        // Process results later
        System.out.println("Product Report:");
        double total = 0;
        for (MatchResult result : results) {
            String product = result.group(1);
            double price = Double.parseDouble(result.group(2));
            total += price;
            
            System.out.printf("Product %s: $%.2f%n", product, price);
        }
        
        System.out.printf("Total value: $%.2f%n", total);
    }
}

在此示例中,我们先存储所有匹配结果,然后再处理它们。 这允许我们将程序的匹配阶段和处理阶段分开。

MatchResult 对象保留所有匹配信息,从而可以在初始匹配完成后进行复杂处理。 此模式对于批处理场景非常有用。

高级 MatchResult 分析

最后一个示例演示了使用多个 MatchResult 对象的高级分析。 我们将比较匹配项并提取关系。

AdvancedMatchResult.java
package com.zetcode;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;

public class AdvancedMatchResult {

    public static void main(String[] args) {
        String input = "user1:file1.txt, user2:file2.doc, user1:file3.pdf, user3:file1.txt";
        String regex = "(\\w+):(\\w+\\.\\w+)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        Map<String, Integer> userFileCounts = new HashMap<>();
        Map<String, Integer> fileUserCounts = new HashMap<>();
        
        while (matcher.find()) {
            MatchResult result = matcher.toMatchResult();
            String user = result.group(1);
            String file = result.group(2);
            
            userFileCounts.put(user, userFileCounts.getOrDefault(user, 0) + 1);
            fileUserCounts.put(file, fileUserCounts.getOrDefault(file, 0) + 1);
        }
        
        System.out.println("Files per user:");
        userFileCounts.forEach((user, count) ->
            System.out.printf("%s: %d files%n", user, count));
            
        System.out.println("\nUsers per file:");
        fileUserCounts.forEach((file, count) ->
            System.out.printf("%s: %d users%n", file, count));
    }
}

此代码分析字符串中用户和文件之间的关系。 我们使用 toMatchResult 捕获每个匹配项并构建统计图。

该示例展示了如何将 MatchResult 对象用于超出简单匹配的复杂分析。 即使在匹配器移动后,不可变的快照也能实现可靠的数据处理。

来源

Java Matcher.toMatchResult 文档

在本文中,我们探讨了 Matcher.toMatchResult 方法及其各种应用。 这项强大的功能可以在 Java 正则表达式处理中实现高级匹配处理和线程安全操作。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员。我于 2007 年开始撰写编程文章,此后撰写了超过 1,400 篇文章和八本电子书。拥有超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程