StringBuilder
ではなくを使用しますStringBuffer
。はマルチスレッドの状況向けであり、同期しないStringBuffer
ため よりも遅くなります。StringBuilder
このスレッドのさまざまな回答でリストされている、これを行うための 4 つの基本的な方法をテストしました。ただし、ここで私がいつも行っている特定の事柄に注意してください。面接担当者が本当に求めているものは次のとおりです。
String += nextCharacter;
を使用するよりもはるかに遅いので、私は決して使用しませんStringBuilder
。
- を設定した
initialCapacity
方が常に速いためです。そうしないと、StringBuilder
いっぱいになると、新しい配列を再割り当てしてコピーする必要がありますが、これは遅くなります。
そしてコード:
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Random;
public class EveryOtherTest {
public static class StringBenchmark extends SimpleBenchmark {
private String input;
protected void setUp() {
Random r = new Random();
int length = r.nextInt(1000) + 1000;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append((char) ('A' + r.nextInt(26)));
}
input = sb.toString();
}
public String timeCharArrayForeach(int reps) {
String output = "";
Random r = new Random();
for (int i = 0; i < reps; i++) {
StringBuilder sb = new StringBuilder(input.length() / 2 + 1);
boolean use = false;
for (char c : input.toCharArray()) {
if(use) sb.append(c);
use = !use;
}
String newOutput = sb.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeCharArrayPlusTwo(int reps) {
String output = "";
Random r = new Random();
for (int i = 0; i < reps; i++) {
StringBuilder sb = new StringBuilder(input.length() / 2 + 1);
char[] charArray = input.toCharArray();
for(int j = 0; j < input.length(); j += 2) {
sb.append(charArray[j]);
}
String newOutput = sb.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeCharAt(int reps) {
String output = "";
Random r = new Random();
for (int i = 0; i < reps; i++) {
StringBuilder tmp = new StringBuilder(input.length() / 2 + 1);
for (int j = 0; j < input.length(); j += 2) {
tmp.append(input.charAt(j));
}
String newOutput = tmp.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeIterator(int reps) {
String output = "";
Random r = new Random();
for(int i = 0; i < reps; i++) {
StringBuilder buf = new StringBuilder(input.length() / 2 + 1);
StringCharacterIterator iterator = new StringCharacterIterator(input);
for (char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) {
buf.append(c);
iterator.next();
}
String newOutput = buf.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeRegex(int reps) {
String output = "";
Random r = new Random();
for(int i = 0; i < reps; i++) {
String newOutput = input.replaceAll("(?<!^).(.)", "$1");
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
}
public static void main(String... args) {
Runner.main(StringBenchmark.class, args);
}
}
結果:
0% Scenario{vm=java, trial=0, benchmark=CharArrayForeach} 2805.55 ns; ?=688.96 ns @ 10 trials
20% Scenario{vm=java, trial=0, benchmark=CharArrayPlusTwo} 3428.48 ns; ?=475.32 ns @ 10 trials
40% Scenario{vm=java, trial=0, benchmark=CharAt} 2138.68 ns; ?=379.44 ns @ 10 trials
60% Scenario{vm=java, trial=0, benchmark=Iterator} 3963.94 ns; ?=389.53 ns @ 10 trials
80% Scenario{vm=java, trial=0, benchmark=Regex} 58743.66 ns; ?=10850.33 ns @ 10 trials
benchmark us linear runtime
CharArrayForeach 2.81 =
CharArrayPlusTwo 3.43 =
CharAt 2.14 =
Iterator 3.96 ==
Regex 58.74 ==============================
vm: java
trial: 0