需要很大的字符串才能产生很大的不同。
这段代码更快的原因是它平均每个循环包含 1.5 个检查,而不是每个循环 3 个检查。它通过使用两个循环来做到这一点,一个用于引用状态,一个用于未引用状态。
public static void main(String... args) {
String s = generateString(20 * 1024 * 1024);
for (int i = 0; i < 15; i++) {
long start = System.nanoTime();
countCharOfString(',', s);
long mid = System.nanoTime();
countCharOfString2(',', s);
long end = System.nanoTime();
System.out.printf("countCharOfString() took %.3f ms, countCharOfString2() took %.3f ms%n",
(mid - start) / 1e6, (end - mid) / 1e6);
}
}
private static String generateString(int length) {
StringBuilder sb = new StringBuilder(length);
Random rand = new Random(1);
while (sb.length() < length)
sb.append((char) (rand.nextInt(96) + 32)); // includes , and "
return sb.toString();
}
public static int countCharOfString2(char c, String s) {
int numberOfC = 0, i = 0;
while (i < s.length()) {
// not quoted
while (i < s.length()) {
char ch = s.charAt(i++);
if (ch == c)
numberOfC++;
else if (ch == '"')
break;
}
// quoted
while (i < s.length()) {
char ch = s.charAt(i++);
if (ch == '"')
break;
}
}
return numberOfC;
}
public static int countCharOfString(char c, String s) {
int numberOfC = 0;
boolean doubleQuotesFound = false;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c && !doubleQuotesFound) {
numberOfC++;
} else if (s.charAt(i) == c && doubleQuotesFound) {
continue;
} else if (s.charAt(i) == '\"') {
doubleQuotesFound = !doubleQuotesFound;
}
}
return numberOfC;
}
印刷
countCharOfString() took 33.348 ms, countCharOfString2() took 31.381 ms
countCharOfString() took 28.265 ms, countCharOfString2() took 25.801 ms
countCharOfString() took 28.142 ms, countCharOfString2() took 14.576 ms
countCharOfString() took 28.372 ms, countCharOfString2() took 14.540 ms
countCharOfString() took 28.191 ms, countCharOfString2() took 14.616 ms