【发布时间】:2016-02-11 09:47:18
【问题描述】:
这段代码比标准的 String.toUpperCase() 函数快大约 3 倍:
public static String toUpperString(String pString) {
if (pString != null) {
char[] retChar = pString.toCharArray();
for (int idx = 0; idx < pString.length(); idx++) {
char c = retChar[idx];
if (c >= 'a' && c <= 'z') {
retChar[idx] = (char) (c & -33);
}
}
return new String(retChar);
} else {
return null;
}
}
为什么速度这么快? String.toUpperCase() 还做了哪些其他工作? 换句话说,是否存在此代码不起作用的情况?
随机长字符串(纯文本)执行 2,000,000 次的基准测试结果:
toUpperString(String) : 3514.339 毫秒 - 大约 3.5 秒
String.toUpperCase() : 9705.397 ms - 差不多 10 秒
** 更新
我添加了“拉丁”检查并将其用作基准(对于那些不相信我的人):
public class BenchmarkUpperCase {
public static String[] randomStrings;
public static String nextRandomString() {
SecureRandom random = new SecureRandom();
return new BigInteger(500, random).toString(32);
}
public static String customToUpperString(String pString) {
if (pString != null) {
char[] retChar = pString.toCharArray();
for (int idx = 0; idx < pString.length(); idx++) {
char c = retChar[idx];
if (c >= 'a' && c <= 'z') {
retChar[idx] = (char) (c & -33);
} else if (c >= 192) { // now catering for other than latin...
retChar[idx] = Character.toUpperCase(c);
}
}
return new String(retChar);
} else {
return null;
}
}
public static void main(String... args) {
long timerStart, timePeriod = 0;
randomStrings = new String[1000];
for (int idx = 0; idx < 1000; idx++) {
randomStrings[idx] = nextRandomString();
}
String dummy = null;
for (int count = 1; count <= 5; count++) {
timerStart = System.nanoTime();
for (int idx = 0; idx < 20000000; idx++) {
dummy = randomStrings[idx % 1000].toUpperCase();
}
timePeriod = System.nanoTime() - timerStart;
System.out.println(count + " String.toUpper() : " + (timePeriod / 1000000));
}
for (int count = 1; count <= 5; count++) {
timerStart = System.nanoTime();
for (int idx = 0; idx < 20000000; idx++) {
dummy = customToUpperString(randomStrings[idx % 1000]);
}
timePeriod = System.nanoTime() - timerStart;
System.out.println(count + " customToUpperString() : " + (timePeriod / 1000000));
}
}
}
我得到了这些结果:
1 String.toUpper() : 10724
2 String.toUpper() : 10551
3 String.toUpper() : 10551
4 String.toUpper() : 10660
5 String.toUpper() : 10575
1 customToUpperString() : 6687
2 customToUpperString() : 6684
3 customToUpperString() : 6686
4 customToUpperString() : 6693
5 customToUpperString() : 6710
这仍然快 60% 左右。
【问题讨论】:
-
您的代码不适用于拉丁字母以外的符号;不注意语言环境等。
-
你是怎么发现这段代码快了 3 倍的?
-
因为
String#toUpperCase()必须处理整个 Unicode,而不仅仅是标准的 latin a-z -
Ěščřžýáíéöťďň 等。也许 Java 9 会有一条快速路径(其中 ASCII 字符串将被更有效地编码),但目前还没有。您只能将代码用于 ASCII 编码。如果您知道可以使用它,请这样做,有支持这种情况的库:Guava's
Ascii#toUpperCase() -
此代码在土耳其语区域设置中是错误的。 'i'(带点的 i)的大写在土耳其语中不是 'I'(不带点的 I),而是 Unicode U+0130(上面带点的拉丁文大写字母 I)
标签: java string performance uppercase lowercase