大きな違いを生むには大きな文字列が必要です。
このコードが高速である理由は、ループごとに3つのチェックではなく、ループごとに平均1.5のチェックが含まれているためです。これは、2つのループを使用して行われます。1つは引用符付きの状態用で、もう1つは引用符なしの状態用です。
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