2

str11、str12、str13、str21、str21、str23 という 6 つの文字列変数があります。

これらの変数の組み合わせを比較する必要があります。

私がチェックしなければならない組み合わせは、1 つのグループとして str11 -- str12 -- str13 と、他のグループとして str21 -- str22 -- str23 です。この 2 つのグループを比較する必要があります。

今、比較にどの方法を使用すればよいか混乱していますか?

同じグループの文字列を追加して比較できますか。これは 1 つの比較のみです( str11 append str12 append str13 ) eqauls ( str21 append str22 append str23 )

または

個別に 3 つの比較を行う必要がありますか?

if( str11 equals str21 ) {

    if( str12 equals str22 ) {

        if( str13 equals str23 ) {

        }

    }

}

文字列比較を行うときに、文字列の長さが原因でコストがかかるパフォーマンス要因は何ですか? すべての文字列が同じ(およそ)長さであると仮定しましょう。

4

8 に答える 8

10

個別にテストします。

「AB」「CD」「EF」は「ABC」「DE」「F」と同じですか?

私はそうは思わない。

PSもしそうなら、それは非常に特殊なケースです。そのように(連結比較として)コーディングすることにした場合は、コメントアウトしてください。

于 2009-01-06T13:35:32.523 に答える
8

比較を 3 つの if ステートメントに分割する必要はまったくありません。また、単純に比較で AND を実行することもできます。

if (  str11 equals str21
   && str12 equals str22
   && str13 equals str23) ...
于 2009-01-06T13:31:57.650 に答える
3

あなたの変数名は、主要なコードの臭いを示しています。6 つの変数を使用する代わりに、それぞれに 3 つの文字列を含む 2 つの配列を使用する必要があるように思えます。言い換えれば、最初は次のようなものがはるかに優れていたはずです。

String[][] strs = new String[2][3];
strs[0][0] = str11;
strs[0][1] = str12;
...

6 つの文字列をどこから取得したかによっては、比較の直前にこれを手動で行う必要はなく、よりわかりやすい形式で引数を渡すことができる可能性があります。

文字列オブジェクトの配列を比較してこれを行いたい場合で、Java 1.5 以降を使用している場合は、配列の等価性のために java.util.Arrays.equals() メソッドにアクセスできることを思い出してください。できる限りライブラリ メソッドを使用することは、車輪を再発明する余分な労力を回避するための優れた方法であり、実装ミスの可能性もあります (たとえば、これまでに提出された実装には両方ともバグがあります)。

あなたがたどる正確なルートはおそらくあなたが書いているドメインに依存します - あなたの特定の問題が常に3つのタプルを比較する必要がある場合、3つの文字列のグループを明示的に比較するコードを書くことはあまり良い考えではありません.おそらく、任意の長さの配列を比較するコードよりもすぐに理解できるでしょう。(このルートに進む場合は、Adam Bellaire が示したように、ネストされた if ブロックの代わりに && を使用した単一の if() 条件を必ず使用してください)。

ただし、一般に、任意の長さの配列で動作するように設定すると、より再利用可能なコード ブロックが得られます。

于 2009-01-07T16:51:15.483 に答える
1

すべての敬意を込めて: あなたのコードと質問は少し臭いがするだけでなく、ほとんど臭いと思います (ここでは大きなスマイリー)。

1) 変数名は実際に文字列ベクトルを持っていることを示します。すでに述べたように
2) 個々の比較と連結された比較の問題は、文字列タプルの等価性をどのように定義するかという問題を引き起こします。も既に述べた。

しかし、私を最も驚かせるのは:

3)私には、「時期尚早の最適化」と間違った場所での CPU サイクルのカウントの典型的なケースのように見えます。

パフォーマンスを本当に重視する場合は、1 回の比較に対する 3 回の個別比較のコストを忘れてください。その代わり:

連結された 2 つの文字列を作成する追加のオーバーヘッドはどうですか?

  (str11 + str12 + str13) = (str21 + str22 + str23)

メモリマネージャーと実行する操作について分析してみましょう。低レベルでは、4 つの追加のメモリ割り当て、2 つの追加の strcpy、およびさらに 4 つの追加の strcat または strcpy (VM の実行方法によって異なりますが、ほとんどは別の strcpy を使用します) 操作が変換されます。次に、最初に strlen を使用して文字数をカウントしない単一の比較が呼び出されます。代わりに、事前にサイズを知っているか (オブジェクト ヘッダーに文字数も含まれている可能性が高い場合)、または単純に 0 バイトまで実行されます。これは 1 回と 3 回呼び出されます。比較する実際の文字数はほぼ同じです (余分な 0 バイトは忘れてください)。これにより、上で説明したオーバーヘッド (数マイクロ秒) に対して、strcmp への 2 つの追加呼び出し (数ナノ秒) が残ります。GC 再利用のオーバーヘッドを合計すると (割り当て 0 対 4)、I'

追加の注意:
理論的には、JITter はそれまたはその一部を最適化し、Adam Bellaire が提案したように実際にコードを生成できますが、JIT 開発者がそのようなコードを最適化することを気にかけているとは思えません。ところで、システムの文字列ルーチン (別名文字列操作) は通常、ハンドコーディングよりもはるかに高速であるため、自分で個々の文字をループし始めないでください。

于 2009-01-13T16:22:56.497 に答える
1

文字列を一緒に追加して比較しても機能しません。たとえば、文字列 1 と 2 は空で、文字列 3 は「gorps」を含み、文字列 4 は「gorps」を含み、5 と 6 は空である可能性があります。追加された結果を比較すると true が返されますが、これは誤検知です。これを機能させるには、どの文字列にも含まれないことを保証する区切り文字を考え出す必要があり、それは面倒になる可能性があります。

私はあなたがやっている方法で比較を行うだけです。読みやすく、簡単です。

于 2009-01-06T13:34:13.977 に答える
1

1 つの大きな char[] に対する反復は、合計で同じ長さの n 個の別個の文字列に対する反復よりもおそらく高速です。これは、データが非常にローカルであり、CPU が簡単にデータをプリフェッチできるためです。

ただし、Java で複数の文字列を連結する場合は、StringBuilder/Buffer を使用してから、いくつかのケースで i を String に変換します。これにより、SB.append() の動作方法と Java String が不変であるため、メモリ割り当てが増加し、メモリのボトルネックが発生し、アプリケーションが大幅に遅くなる可能性があります。

文字列をそのままにして、個別に比較することをお勧めします。より長い char[] によるパフォーマンスの向上は、より高い割り当て率で発生する可能性がある問題よりもはるかに少ない可能性があります。

于 2009-01-06T14:11:47.723 に答える
0

2 つのグループを 2 つの配列に追加し、配列をループして、その配列内の個々の文字列を比較します。良い例は、Markus Lausberg によって与えられたアンサーに既にあります。

パフォーマンスのコストについては心配しません。できるだけ読みやすい方法で書いてください。Java コンパイラは、パフォーマンスの最適化において非常に優れています。

方法の例:

    public boolean compareGroups(String[] group1, String[] group2){
    if (group1.length != group2.length ){
        return false;
    }

    for (int i = 0; i < group1.length; i++) {
        if (!group1[i].equals(group2[i])){
            return false;
        }
    }

    return true;
}

そして、メソッドの呼び出しはもちろん簡単です:

        String[] group1 = new String[]{"String 1", "String 2", "String 3"};
    String[] group2 = new String[]{"String 1", "String 2", "String 3"};

    boolean result = compareGroups(group1, group2);
于 2009-01-06T14:19:53.683 に答える
0

私は簡単な方法を使用します

両方の配列のすべての配列要素を動的に実行します。

            boolean isEqual = true;
            for(int n = 0;n<str1.length;++n){
                isEqual &= str1[n].equals(str2[n]);
            }

            return isEqual;
于 2009-01-06T13:35:25.457 に答える