如何计算正则表达式的匹配项数?

假设我有一个包含以下内容的字符串:

HelloxxxHelloxxxHello

我编译了一个模式来寻找‘ Hello’

Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher("HelloxxxHelloxxxHello");

它应该能找到三个匹配的,我怎么才能计算出有多少个匹配的呢?

我已经尝试了各种循环,并使用 matcher.groupCount(),但它不工作。

123609 次浏览

matcher.find()没有找到 所有匹配,只有 下一个匹配。

Java9 + 的解决方案

long matches = matcher.results().count();

Java8及以上版本的解决方案

您必须执行以下操作。(从 Java9开始,有一个更好的解决方案)

int count = 0;
while (matcher.find())
count++;

顺便说一下,matcher.groupCount()是完全不同的东西。

完整例子 :

import java.util.regex.*;


class Test {
public static void main(String[] args) {
String hello = "HelloxxxHelloxxxHello";
Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher(hello);


int count = 0;
while (matcher.find())
count++;


System.out.println(count);    // prints 3
}
}

Handling overlapping matches

当计算 aaaaaa的匹配时,上面的代码片段将给出 2

aaaa
aa
aa

为了得到3个匹配,也就是这个行为:

aaaa
aa
aa
aa

您必须在 <start of last match> + 1索引处搜索匹配项,如下所示:

String hello = "aaaa";
Pattern pattern = Pattern.compile("aa");
Matcher matcher = pattern.matcher(hello);


int count = 0;
int i = 0;
while (matcher.find(i)) {
count++;
i = matcher.start() + 1;
}


System.out.println(count);    // prints 3

这应该适用于可能重叠的匹配:

public static void main(String[] args) {
String input = "aaaaaaaa";
String regex = "aa";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
int from = 0;
int count = 0;
while(matcher.find(from)) {
count++;
from = matcher.start() + 1;
}
System.out.println(count);
}

如果您希望使用 Java8流,并且对 while循环过敏,您可以尝试这样做:

public static int countPattern(String references, Pattern referencePattern) {
Matcher matcher = referencePattern.matcher(references);
return Stream.iterate(0, i -> i + 1)
.filter(i -> !matcher.find())
.findFirst()
.get();
}

免责声明: 这只适用于不相交的匹配。

例如:

public static void main(String[] args) throws ParseException {
Pattern referencePattern = Pattern.compile("PASSENGER:\\d+");
System.out.println(countPattern("[ \"PASSENGER:1\", \"PASSENGER:2\", \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\", \"PASSENGER:1\" ]", referencePattern));
System.out.println(countPattern("[  ]", referencePattern));
}

这个打印出来:

2
0
1
0

这是一个针对流不相交匹配的解决方案:

public static int countPattern(String references, Pattern referencePattern) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
new Iterator<Integer>() {
Matcher matcher = referencePattern.matcher(references);
int from = 0;


@Override
public boolean hasNext() {
return matcher.find(from);
}


@Override
public Integer next() {
from = matcher.start() + 1;
return 1;
}
},
Spliterator.IMMUTABLE), false).reduce(0, (a, c) -> a + c);
}

使用下面的代码查找正则表达式在输入 中找到的匹配项数量

        Pattern p = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL);// "regex" here indicates your predefined regex.
Matcher m = p.matcher(pattern); // "pattern" indicates your string to match the pattern against with
boolean b = m.matches();
if(b)
count++;
while (m.find())
count++;

这是一个通用的代码,但不是特定的代码,可以根据您的需要进行调整

Please feel free to correct me if there is any mistake.

在 Java9中,可以使用 Matcher.results()提供的流

long matches = matcher.results().count();