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
追記: ソースで嘘ついてたから修正