0

以下は、すべてのアナグラムを文字列のコレクションに並べて配置するために私が書いたコードです。出力は期待どおりにソートされません。実際、出力は入力と同じです。どこが間違っていますか?

package set2;

import java.util.Arrays;
import java.util.Comparator;

public class printAllAnagrams {
    public static void main(String[] args) {
        String[] s = { "Harsha", "ant", "sha", "tna", "ash" };
        sortAnagrams(s);
        for (String e : s) {
            System.out.println(e);
        }
    }

    private static void sortAnagrams(String[] s) {
        Arrays.sort(s, new Comparator<String>() {

            @Override
            public int compare(String s1, String s2) {
                s1.toLowerCase();
                s2.toLowerCase();

                if (s1.length() != s2.length()) {
                    return -1;
                } else {
                    char[] s1_char = s1.toCharArray();
                    char[] s2_char = s2.toCharArray();
                    Arrays.sort(s1_char);
                    Arrays.sort(s2_char);

                    for (int i = 0; i < s1_char.length; i++) {
                        if (s1_char[i] != s2_char[i]) {
                            return -1;
                        }
                    }
                }
                return 0;
            }

        });

    }
}
4

6 に答える 6

0

javadocから:

実装者はsgn(compare(x,y)) == -sgn(compare(y,x))、すべてのxy. (これcompare(x,y)は、 が例外をスローする場合にのみ例外をスローする必要があることを意味しcompare(y,x)ます。)

これは基本的に、呼び出すcompare(s1,s2)と -1 * を生成する必要がcompare(s2,s1)あり、どちらのreturn -1;ステートメントもこれに続かないことを意味します。その代わりに、int と文字を互いに比較してその値を返すことができます。たとえば、次のコードは (の代わりにreturn -1;) 機能します。

return Integer.compare(s1.length(),s2.length()); //for the ints

return Character.compare(s1_char[i],s2_char[i]); //for the chars

Vishal's answer も見てください。これは別のバグです。

于 2013-03-20T15:49:02.690 に答える
0

これは確かに正しいとは言えません:

if (s1.length() != s2.length()) {
    return -1;
}

それは ifs1.length() != s2.length() s1 < s2 s2 < s1を意味します。

私があなたがすることを意味すると思います:

public int compare(String s1, String s2) {
    if (s1.length() == s2.length()) {                   
        char[] s1_char = s1.toLowerCase().toCharArray();
        char[] s2_char = s2.toLowerCase().toCharArray();
        Arrays.sort(s1_char);
        Arrays.sort(s2_char);

        for (int i = 0; i < s1_char.length; i++) {
            if (s1_char[i] != s2_char[i]) {
                return (int)(s1_char[i] - s2_char[i]);
            }
        }
        return 0;
    } else {
        return s1.length() - s2.length();
    }
}
于 2013-03-20T15:41:26.530 に答える
0

次のことをしてみませんか。

        @Override
        public int compare(String s1, String s2) {
            return s1.toLowerCase().compareTo(s2.toLowerCase());
        }
于 2013-03-20T15:41:57.543 に答える
0

これはよく見ないと

 s1.toLowerCase();

は変更されませんが、 の小文字のバリアントである新しいs1文字列を返します。Java では文字列は不変です。したがって、上記から返された値を収集して操作する必要があります。s1

于 2013-03-20T15:40:50.780 に答える
0

あなたのコンパレータはまったく安定していません。

return -1長さが違う場合はまずあなた。これは、オペランドの順序によっては、「asbd」>「ash」またはその逆になる可能性があることを意味します。

また、char 比較でも同じことを行います。

if (s1_char[i] != s2_char[i]) {
   return -1;
}

これを次のように置き換えます。

if (s1_char[i] != s2_char[i]) {
  return s1_char[i] > s2_char[i] ? 1 : -1;
}

長さの比較には同じパターンを使用します。

EDITメソッドから-1を返すことは、ドキュメントcompareに従って、最初のオペランドが2番目よりも小さいことを意味します。

于 2013-03-20T15:42:48.697 に答える
0

文字列は不変であるため、オブジェクトでメソッドを呼び出すだけではString、それ自体は変更されませんString。以下を使用する必要があります。

s1 = s1.toLowerCase();
s2 = s2.toLowerCase();
于 2013-03-20T15:44:38.450 に答える