あなたの質問は私にパフォーマンスについて疑問に思いました。最近、構文を掘り下げたという理由だけで、可能な限りGuavaのSplitterを使用しています。パフォーマンスを測定したことがないので、4つの解析スタイルの簡単なテストをまとめました。私はこれらを非常に迅速にまとめたので、スタイルとエッジケースの正確さの間違いを許してください。これらは、2番目と4番目の項目にのみ関心があるという理解に基づいています。
私が興味深いと思ったのは、「homeGrown」(実際には粗いコード)ソリューションが、350MBのタブ区切りテキストファイル(4列)を解析するときに最速であるということです。例:
head test.txt
0 0 0 0
1 2 3 4
2 4 6 8
3 6 9 12
ラップトップで350MBを超えるデータを操作すると、次の結果が得られました。
- 自家製:2271ms
- guavaSplit:3367ms
- 正規表現:7302ms
- トークン化:3466ms
それを考えると、私はほとんどの作業でGuavaのスプリッターを使い続け、より大きなデータセットのカスタムコードを検討すると思います。
public static List<String> tokenize(String line){
List<String> result = Lists.newArrayList();
StringTokenizer st = new StringTokenizer(line, "\t");
st.nextToken(); //get rid of the first token
result.add(st.nextToken()); //show me the second token
st.nextToken(); //get rid of the third token
result.add(st.nextToken()); //show me the fourth token
return result;
}
static final Splitter splitter = Splitter.on('\t');
public static List<String> guavaSplit(String line){
List<String> result = Lists.newArrayList();
int i=0;
for(String str : splitter.split(line)){
if(i==1 || i==3){
result.add(str);
}
i++;
}
return result;
}
static final Pattern p = Pattern.compile("^(.*?)\\t(.*?)\\t(.*?)\\t(.*)$");
public static List<String> regex(String line){
List<String> result = null;
Matcher m = p.matcher(line);
if(m.find()){
if(m.groupCount()>=4){
result= Lists.newArrayList(m.group(2),m.group(4));
}
}
return result;
}
public static List<String> homeGrown(String line){
List<String> result = Lists.newArrayList();
String subStr = line;
int cnt = -1;
int indx = subStr.indexOf('\t');
while(++cnt < 4 && indx != -1){
if(cnt==1||cnt==3){
result.add(subStr.substring(0,indx));
}
subStr = subStr.substring(indx+1);
indx = subStr.indexOf('\t');
}
if(cnt==1||cnt==3){
result.add(subStr);
}
return result;
}
これらはすべて、適切な境界チェックとより洗練された実装を使用すると遅くなる可能性があることに注意してください。