前言
今天帮同事写正则,突然发现matcher里的find与matches方法开始并不能讲清区别,记录下
正文
find()与matches()的区别:
find():是否存在与该模式匹配的下一个子序列。简单来说就是在字符某部分匹配上模式就会返回true,同时匹配位置会记录到当前位置,再次调用时从该处匹配下一个。
matches():整个字符串是否匹配上模式,匹配上则返回true,否则false。
需要注意的是:
- 如果先调用 matches(),再调用find(),会导致find匹配不成功;
反之,先调用find(),再调用matches()不会影响。(原因在下面会分析)
可以使用find的带参数的方法,传入0即可,find(0)。 - 如果没有匹配上,调用start()时会抛错。
原因
find方法会去找上一次匹配后的标识符,然后去匹配,
matches直接使用传入字符的起始位置,并会在匹配结束成功后将匹配标识符置到最后。
可以看下源码,如下
//Matcher 类
/**
* The range within the sequence that is to be matched. Anchors
* will match at these "hard" boundaries. Changing the region
* changes these values.
*/
//这个是字符的起始和结束
int from, to;
/**
* The range of string that last matched the pattern. If the last
* match failed then first is -1; last initially holds 0 then it
* holds the index of the end of the last match (which is where the
* next search starts).
*/
//这个就是上一次匹配的范围,注意调用start()时如果first为-1会向外抛错
int first = -1, last = 0;
/**
* The end index of what matched in the last match operation.
*/
int oldLast = -1;
//初始化matcher时会调用这个方法,from,to赋值
public Matcher reset() {
first = -1;
last = 0;
oldLast = -1;
for(int i=0; i<groups.length; i++)
groups[i] = -1;
for(int i=0; i<locals.length; i++)
locals[i] = -1;
lastAppendPosition = 0;
from = 0;
to = getTextLength();
return this;
}
//matches使用的是from,并会在结束后,将标识符置到末尾
public boolean matches() {
return match(from, ENDANCHOR);
}
boolean match(int from, int anchor) {
this.hitEnd = false;
this.requireEnd = false;
from = from < 0 ? 0 : from;
this.first = from;
this.oldLast = oldLast < 0 ? from : oldLast;
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
acceptMode = anchor;
boolean result = parentPattern.matchRoot.match(this, from, text);
if (!result)
this.first = -1;
this.oldLast = this.last;
return result;
}
//find是直接使用的之前的last,所以如果在matches匹配成功后,再用find就不行了。当然可以使用find(0)
public boolean find() {
int nextSearchIndex = last;
if (nextSearchIndex == first)
nextSearchIndex++;
// If next search starts before region, start it at region
if (nextSearchIndex < from)
nextSearchIndex = from;
// If next search starts beyond region then it fails
if (nextSearchIndex > to) {
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
return false;
}
return search(nextSearchIndex);
}