我有一个函数来检查一个字符串(大多数字符串只有一个CJK字符)是否只有单词字符,并且它将被调用很多次,所以成本是不可接受的,但我不知道如何优化它,有什么建议吗?
/*\w is equivalent to the character class [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}].
For more details see Unicode TR-18, and bear in mind that the set of characters
in each class can vary between Unicode releases.*/
private static final Pattern sOnlyWordChars = Pattern.compile("\\w+");
private boolean isOnlyWordChars(String s) {
return sOnlyWordChars.matcher(s).matches();
}
当s为“3g”或“go_url”或“hao123”时,isOnlyWordChars(s)应该返回true。
答案 0 :(得分:4)
private boolean isOnlyWordChars(String s) {
char[] chars = s.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
更好的实施
public static boolean isAlpha(String str) {
if (str == null) {
return false;
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
if (Character.isLetter(str.charAt(i)) == false) {
return false;
}
}
return true;
}
或者如果您使用的是Apache Commons,StringUtils.isAlpha()。答案的第二个实现实际上来自源码,如果isAlpha。
<强>更新强>
对不起迟到的回复。我不太确定速度,虽然我在几个地方读到循环比正则表达式更快。为了确保我在ideoone中运行以下代码,结果是
5000000次迭代
使用您的代码: 4.99秒(之后的运行时错误,因此对于大数据不起作用)
我的第一个代码 2.71秒
使用我的第二个代码 2.52秒
进行500000次迭代
使用您的代码: 1.07秒
我的第一个代码 0.36秒
我的第二个代码 0.33秒
Here是我使用的示例代码。
N.B。可能会有小错误。您可以使用它来测试不同的场景。 根据Jan的评论,我认为这些是使用私人或公共的小事。条件检查是一个很好的观点。
答案 1 :(得分:1)
我唯一看到的是将你的模式改为:
^\\w++$
但我不是java专家
说明:
我添加了锚点(即^
$
),增加了模式的性能(正则表达式引擎在第一个非单词字符处失败,直到遇到结束)。我添加了一个占有量词(即++
),然后正则表达式引擎与回溯位置无关,而且速度更快。
更多信息here。
答案 2 :(得分:1)
我认为主要问题是你的模式。
当我注意到我的一个测试字符串Supercalifragilisticexpalidociou5
失败时,我正在处理迭代解决方案。这样做的原因是:\w+
只关心是否有一个或多个单词字符。 如果您没有查看已经匹配的单词,则无关紧。
要解决此问题,请使用以下方法:
(?!\W+)(\w+)
如果发现一个或多个字符是非单词字符(例如&amp; *()!@!#$),\W+
条件将锁定正则表达式。
答案 3 :(得分:1)
如果你想用正则表达式做这个,那么最有效的方法是将逻辑改为否定;即“每个字母都是一个字母”变成“没有字符是非字母”。
private static final Pattern pat = Pattern.compile("\\W");
private boolean isOnlyWordChars(String s) {
return !pat.matcher(s).find();
}
这将最多测试一次每个角色......没有回溯。