私はstring
が特定の文字で始まり、dataset
をループしていて、私のdataset
が大きいと予想されるかどうかに基づいて分岐するJavaでコードを書いています。"startsWith"は "indexOf"より高速ですか?
startsWith
がindexOf
より速いかどうか疑問に思っていました。私は2000年のレコードを試しましたが、違いは見つかりませんでした。
私はstring
が特定の文字で始まり、dataset
をループしていて、私のdataset
が大きいと予想されるかどうかに基づいて分岐するJavaでコードを書いています。"startsWith"は "indexOf"より高速ですか?
startsWith
がindexOf
より速いかどうか疑問に思っていました。私は2000年のレコードを試しましたが、違いは見つかりませんでした。
public class Test
{
public static void main(String args[]) {
long value1 = System.currentTimeMillis();
for(long i=0;i<100000000;i++)
{
"abcd".indexOf("a");
}
long value2 = System.currentTimeMillis();
System.out.println(value2-value1);
value1 = System.currentTimeMillis();
for(long i=0;i<100000000;i++)
{
"abcd".startsWith("a");
}
value2 = System.currentTimeMillis();
System.out.println(value2-value1);
}
}
このコードでテストし、startsWithは、文字列をたどる必要がないという明白な理由から、より優れているようです。しかし、最良のシナリオの両方が0
は、あなたがのためにパフォーマンスのボトルネックとしてテストを同定している最悪のシナリオでのstartsWithは常に
おそらく、一致しない場合は、検索が停止する可能性がありますが、indexOfは後で文字列を検索する必要があります。
が(B)が結合しているa.startsWithの実行時間は、Bの長さ:
でも源に見なく、それのstartsWithが速く少なくとも大ストリングと短いパターンのためのものであることは明らかです。多くても最初のb文字がチェックされた後、検索は終了します。
a.indexOf(b)の実行時間は(actual algorithmに応じて)大きくなります。すべてのアルゴリズムには、aの長さに応じて少なくとも実行時間があります。おおまかに言えば、パターンがその位置から始まるかどうかを確認するためには、各文字を一度見なければならないということです。
実際、実際の使用方法に違いがある場合は、実際の使用方法によって異なります。実生活の違いを測ることは決して悪くありません。
私はあなたの最初の文が後ろ向きだと思います... * startsWith *は、大きな文字列と短いパターンの場合は、もっと速くなります。 –
Jon Skeetが正しいです。私はそれを変えた。 – dmeister
一般に、マイクロ最適化のゴールデンルールは、ここで適用されます。
「測定する、推測しない」
このタイプのすべての最適化と同様に、数千文字の文字列が何百万もあることを確認しない限り、2つの呼び出しの違いはほとんど関係ありません。
コードを使用してプロファイラを実行し、あなたの速度が低下していると測定できる場合にのみ、この呼び出しを最適化します。それまでは、読みやすいオプション(この場合はstartsWith)を使用してください。このブロックがあなたを減速させていることがわかったら、両方を試し、どちらか速い方を使用してください。リンス。繰り返す;-)
学問的には、私の推測では、startsWithはindexOfを使用して実装されている可能性があります。ソースコードを確認し、興味があるかどうか確認してください。
(startsWithはindexOfを呼び出さないことがわかります)
私は実際には、startsWithがindexOfで実装されていないことを本当に望んでいます。 .startsWith( "x") - 効率的な実装は最初の文字をチェックした後に戻ってくるはずですが、indexOfを使うと潜在的に文字列全体を調べる必要があります。 –
それは良い点です。私は今好奇心が強いので、私はチェックするつもりです。 –
私はチェックし、startsWithはindexOfを呼び出さない。危機が鎮圧された。 –
startsWith
文字列の最初の位置にあるかどうかを確認するだけで済みます。
私の推測では、2000年のレコードは数ミリ秒で完了しました(その場合)。 1つのアプローチを別のアプローチに対してベンチマークしたい場合は、タイミングの違いが重要になるほど十分な時間をかけて実行してください。私は、10-30秒が大幅に改善されていることが分かりますが、テストを複数回実行するのに十分な時間がかかります。 (これは私はおそらく長い時間のために試してみた私のベンチマークのほとんどは楽しみのためにある本格的な調査だったら。。)
また、あなたが変化したデータ持っていることを確認します - indexOf
とstartsWith
はほぼ同じ走行時間を持っている必要がありますindexOf
が0の場合が返されます。したがって、すべてのレコードがパターンと一致する場合、実際には正しくテストされていません。 (私はそれがあなたのテストの場合に当てはまるかどうかはわかりません - それはただ気にするものです。)
あなたは、データセットが大きいと予想されていると述べました。だから、私は多くのperformanveがこのデータセットにアクセスし、メモリ内でそれを処理するだろうと確信しています。つまり、どちらか一方を使用しても性能が大きく変わることはありません。しかし、これが重要なのであれば、標準的なライブラリメソッドよりもはるかに速い独自のstartWithメソッドを記述するか、少なくとも何が行われているかを正確に知ることができます。
のstartsWithはのindexOfの==より明確であるのindexOfよりも良好に機能する一方近くに実行する必要がありますあなたは読みやすさを犠牲にする必要がありますか?
ただし、startsWithは常にindexOfで置き換えることができますが、注意してください。 startsOithでindexOfを置き換えることはできません。そういう意味で、オレンジとリンゴの比較があります。文字列が特定の文字セットで始まっているかどうかを確認したい場合は、両方を使用できるかもしれません。まだ起動していることをお勧めします。 – Priyank
"indexOfが0を返した場合、indexOfとstartsWithの実行時間はおおよそ同じでなければなりません。"このテストではJonが心配していた問題があります。これは大きなベンチマークではないかもしれません。 –
"input"に複数の文字が含まれていると、indexOfが高速になります。 startsWithは一文字で高速です。単語が長ければ長いほど、indexOfはより良い結果を出します。 100回の反復でループを行い、代わりにSystem.nanoTime()を使用してください。しかし、結果は非常に小さいので、どちらを使うか心配する必要はありません。 –