JDK 1.5からのString.formatって遅いの?

こうしたい
123456789 ⇒ 123,456,789

料金を3桁のカンマ区切りで表示しようと思って、「今回はJDK1.5だからString.formatでいっか」ってガリガリしてたら、
先輩から「一度書式文字列をパースしてるだろうから、自分で書いたほうが早いんじゃない?」との言葉。
試してみた。

OS: Windows XP SP2
JDK: 1.5
CPU: Core 2 Duo E6550
メモリ: 3.25G
条件:0から100万までを3桁カンマ区切りに整形するのにかかった時間をミリ秒で計測
結果:

String.format 10218ms
自分で書いた(1) 688ms
自分で書いた(2) 969ms
DecimalFormat 1562ms
NumberFormat 18719ms

結構違うけれど、100万回でこの程度なら許容範囲…なのかな?


以下、自分で書いたところがバッちいけれどソース。

// String.format
long a1 = System.currentTimeMillis();
for (int i=-500000; i<500000; i++) {
  String.format("%1$,3d", i);
}
long a2 = System.currentTimeMillis();
System.out.println("StringFormat:"+(a2-a1)+"ms");

結果:10218ms
// 自分で書いてみた pt.1
long b1 = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
  insertComma(i);
}
long b2 = System.currentTimeMillis();
System.out.println("MyFormatter1:"+(b2-b1)+"ms");

結果:688ms

public static String insertComma(long value) {

  boolean isMinus = false;
  
  StringBuffer sb = new StringBuffer();
  if (value<0) {
    sb.append(String.valueOf(value).substring(1));
    isMinus = true;
  } else {
    sb.append(value);
  }
  
  int oh = sb.length()%3;
  
  int count = 0;
  while ((oh+(count*4))<sb.length()) {
    if (0==oh && (oh+(count*4)==0)){
      count++;
      continue;
    } else if (0==oh) {
      sb.insert((oh+(count*4)-1), ",");
    } else {
      sb.insert((oh+(count*4)), ",");
    }
    count++;
  }
  if (isMinus) {
    sb.insert(0, "-");
  }
  
  return sb.toString();
}
// 自分で書いてみた pt.2
long c1 = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
  insertComma2(i);
}
long c2 = System.currentTimeMillis();
System.out.println("MyFormatter:"+(c2-c1)+"ms");

結果:969ms

public static String insertComma2(long value) {

  boolean isMinus = false;
  
  String v;
  if (value<0) {
    v = String.valueOf(value).substring(1);
    isMinus = true;
  } else {
    v = String.valueOf(value);
  }
  
  char[] vArray = v.toCharArray();
  int count = 0;
  StringBuffer sb = new StringBuffer();
  for (int i=vArray.length-1; i>=0; i--) {
    if (count==3) {
      count = 0;
      sb.insert(0, ",");
    }
    sb.insert(0, vArray[i]);
    count++;
  }
  if (isMinus) {
    sb.insert(0, "-");
  }
  
  return sb.toString();
}
// DecimalFormat
DecimalFormat f = new DecimalFormat("#,###");
long d1 = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
  f.format(i);
}
long d2 = System.currentTimeMillis();
System.out.println("DecimalFormat:"+(d2-d1)+"ms");

結果:1562ms
// NumberFormat
NumberFormat n = NumberFormat.getIntegerInstance(Locale.US);
long e1 = System.currentTimeMillis();
for (int i=0; i<10000000; i++) {
  n.format(i);
}
long e2 = System.currentTimeMillis();
System.out.println("NumberFormat:"+(e2-e1)+"ms");

結果:18719ms


追記: ソースで嘘ついてたから修正