一、Pattern & Matcher 核心介绍📌

java.util.regex.PatternMatcher是 Java 正则表达式核心 API:

  1. Pattern:正则表达式编译模板,负责将正则字符串编译成正则模式,无法直接实例化,通过Pattern.compile(正则)静态方法创建。
  2. Matcher:匹配器对象,由pattern.matcher(目标字符串)生成,提供分组查找、位置匹配、提取子串等方法,是真正执行正则匹配的对象。

常用方法:

  • find():从当前位置向后查找匹配内容,找到返回 true;
  • group(n):获取第 n 分组匹配到的子串(group()等价group(0),取整体匹配内容);
  • start()/end():返回匹配子串起始、结束下标。

二、需求说明

原始账单文本:

plaintext

从3到8匹配的子序列:76.89
从12到17匹配的子序列:67.38
从21到26匹配的子序列:12.68
通信总费用:156.95元
三地的平均气温:[-1.0, 15.5, -18.0]
三地的平均气温(升序):[-18.0, -1.0, 15.5]

业务需求:

  1. 提取所有小数数字,计算账单金额总和;
  2. 提取括号内气温数值,计算三地平均气温、排序。

正则设计

  • 匹配小数正则:-?\\d+\\.\\d+-?可选负号、整数位、小数点、小数位)

三、完整实现代码

java

运行

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternMatcherDemo {
    public static void main(String[] args) {
        // 原始文本
        String content = "从3到8匹配的子序列:76.89\n" +
                "从12到17匹配的子序列:67.38\n" +
                "从21到26匹配的子序列:12.68\n" +
                "通信总费用:156.95元\n" +
                "三地的平均气温:[-1.0, 15.5, -18.0]\n" +
                "三地的平均气温(升序):[-18.0, -1.0, 15.5]";

        // 1.编译正则模板:匹配正负小数
        String reg = "-?\\d+\\.\\d+";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(content);

        List<Double> allNum = new ArrayList<>();
        List<Double> tempList = new ArrayList<>();

        // 2.循环查找所有匹配数字
        while (matcher.find()) {
            String numStr = matcher.group();
            double num = Double.parseDouble(numStr);
            allNum.add(num);
            System.out.println("匹配数值:"+numStr+"  匹配区间:["+matcher.start()+"~"+matcher.end()+"]");
        }

        // 拆分:账单费用(前4个)、气温(后3个)
        List<Double> costList = allNum.subList(0,4);
        tempList.addAll(allNum.subList(4,7));

        // 账单费用求和
        double totalCost = 0;
        for(Double cost:costList){
            totalCost += cost;
        }
        System.out.println("\n===账单统计===");
        System.out.println("各项费用:"+costList);
        System.out.println("通信总费用合计:"+totalCost+"元");

        // 气温计算:平均值+升序排序
        double avgTemp = 0;
        for(Double t:tempList) avgTemp += t;
        avgTemp /= tempList.size();
        Collections.sort(tempList);
        System.out.println("\n===气温统计===");
        System.out.println("原始气温数组:"+allNum.subList(4,7));
        System.out.println("气温升序数组:"+tempList);
        System.out.println("三地平均气温:"+avgTemp);
    }
}

四、运行结果

plaintext

匹配数值:76.89  匹配区间:[20~25]
匹配数值:67.38  匹配区间:[45~50]
匹配数值:12.68  匹配区间:[70~75]
匹配数值:156.95  匹配区间:[87~93]
匹配数值:-1.0  匹配区间:[111~115]
匹配数值:15.5  匹配区间:[117~121]
匹配数值:-18.0  匹配区间:[124~129]

===账单统计===
各项费用:[76.89, 67.38, 12.68, 156.95]
通信总费用合计:313.9元

===气温统计===
原始气温数组:[-1.0, 15.5, -18.0]
气温升序数组:[-18.0, -1.0, 15.5]
三地平均气温:-1.1666666666666667

五、核心知识点解析💡

1.Pattern 编译优化

Pattern.compile()编译正则开销大,频繁使用的正则建议全局静态常量,避免重复编译:

java

运行

private static final Pattern NUM_PATTERN = Pattern.compile("-?\\d+\\.\\d+");

2.Matcher 三个关键方法

表格

方法 作用
find() 游标向后搜索,每次找到一个匹配就暂停,下次继续向后
group() 返回本次匹配到的完整字符串
start()/end() 获取当前匹配内容在原字符串中的起始、结束索引

3. 正则细节说明

  • -?:负号可选,兼容负数气温-18.0
  • \\d+:小数点前整数部分(1 个及以上数字);
  • \\.:转义小数点(.在正则代表任意字符,必须转义);
  • \\d+:小数点后小数位。

六、拓展场景

  1. 分组提取:如需单独提取括号内容,可改用分组正则\\[((-?\\d+\\.\\d+,?\\s*)+)\\],用group(1)取出括号内全部气温字符串;
  2. 全局忽略大小写:编译时加参数Pattern.CASE_INSENSITIVEPattern.compile(reg,Pattern.CASE_INSENSITIVE)
  3. 多行匹配Pattern.DOTALL.匹配换行符。

更多推荐