Java8時代の文字列連結まとめ
面白かったので、もうちょい速くしてみました。
public static String stringBuilderJoinMem2() {
StringBuilder s = new StringBuilder(9000);
s.append('[');
for (int i = 0, l = strarray.length; i < l; ++i) {
s.append(strarray[i]);
s.append(']');
s.append(',');
s.append('[');
}
s.setLength(s.length() - 3);
s.append(']');
return s.toString();
}
自分の環境ではstringBuilderJoinMemよりも100msくらい速くなりました。
デリミタが固定でいいならcharをappendした方が速いです。Stringやchar[]のappendはSystem#arraycopy()が行われるため、JNIのオーバーヘッドがボトルネックになっているような気がします。
System.arraycopyは遅いの?
測ってみました。Javaコードによる配列のコピーとSystem#arraycopy(JNI)による配列のコピーにかかる時間を計測してみました。
public class Bench {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
test(i, 5000000);
}
}
private static void test(int size, int count) {
char[] src = new char[size];
char[] dst = new char[size];
for (int i = 0; i < 10000; i++) {
System.arraycopy(src, 0, dst, 0, src.length);
}
long time = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
System.arraycopy(src, 0, dst, 0, src.length);
}
System.out.println("native:" + size + ":" + (System.currentTimeMillis() - time));
for (int i = 0; i < 10000; i++) {
arraycopy(src, 0, dst, 0, src.length);
}
time = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
arraycopy(src, 0, dst, 0, src.length);
}
System.out.println("java:" + size + ":" + (System.currentTimeMillis() - time));
}
private static void arraycopy(char[] src, int srcPos, char[] dst, int dstPos, int len) {
for (int i = 0; i < len; i++) {
src[i + srcPos] = dst[i + dstPos];
}
}
}
native:0:10
java:0:12
native:1:40
java:1:14
native:2:24
java:2:17
native:3:21
java:3:15
native:4:28
java:4:27
native:5:35
java:5:32
native:6:26
java:6:40
native:7:23
java:7:36
native:8:33
java:8:40
native:9:29
java:9:43
native:10:31
java:10:48
native:11:28
java:11:49
native:12:37
java:12:55
native:13:35
java:13:58
native:14:39
java:14:63
native:15:34
java:15:61
native:16:38
java:16:66
native:17:22
java:17:70
native:18:25
java:18:73
native:19:23
java:19:91
要素数が5くらいまでなら、System#arraycopyよりJavaで直接実行した方が速いですね。