(调用 )的行为在 Java 7 和 Java 8 之间变化。String.split
Pattern.split
文档
比较 Java 7 和 Java 8 中的文档,我们观察到添加了以下子句:Pattern.split
当输入序列的开头存在正宽度匹配时,则在结果数组的开头包含一个空的前导子字符串。但是,开头的零宽度匹配永远不会产生这样的空前导子字符串。
与Java 7相比,Java 8中也添加了相同的子句。String.split
参考实现
让我们比较 Java 7 和 Java 8 中引用实现的代码。该代码是从版本 7u40-b43 和 8-b132 的 grepcode 中检索的。Pattern.split
Java 7
public String[] split(CharSequence input, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = matcher(input);
// Add segments before each match found
while(m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index,
input.length()).toString();
matchList.add(match);
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return new String[] {input.toString()};
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}
爪哇 8
public String[] split(CharSequence input, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = matcher(input);
// Add segments before each match found
while(m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index,
input.length()).toString();
matchList.add(match);
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return new String[] {input.toString()};
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}
在 Java 8 中添加以下代码将排除输入字符串开头的零长度匹配,这解释了上述行为。
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
保持兼容性
Java 8 及更高版本中的以下行为
要使行为在各个版本之间保持一致并与 Java 8 中的行为兼容,请执行以下操作:split
- 如果您的正则表达式可以匹配零长度字符串,只需在正则表达式的末尾添加,并将原始正则表达式包装在非捕获组中(如有必要)。
(?!\A)
(?:...)
- 如果您的正则表达式无法匹配零长度字符串,则无需执行任何操作。
- 如果您不知道正则表达式是否可以匹配零长度字符串,请执行步骤 1 中的两个操作。
(?!\A)
检查字符串是否不在字符串的开头结束,这意味着匹配项在字符串的开头是空匹配项。
Java 7 及更早版本中的以下行为
没有通用的解决方案可以使 Java 7 及更早版本向后兼容,除了替换指向您自己的自定义实现的所有实例之外。split
split