【问题标题】:Comparator not giving the expected result比较器没有给出预期的结果
【发布时间】:2013-03-09 19:33:05
【问题描述】:

下面是我编写的代码,用于将所有字谜放在一个字符串集合中。 输出没有按预期排序。实际上,输出与输入相同。 我哪里错了?

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;
            }

        });

    }
}

【问题讨论】:

  • 调试您的代码以验证您的期望。

标签: java sorting anagram


【解决方案1】:

这不一定是对的:

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

这意味着如果s1.length() != s2.length() s1 &lt; s2 s2 &lt; 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();
    }
}

【讨论】:

  • @downvoter 如果我运行此代码,它会给出sha ash ant tna Harsha... 这似乎正是所要求的...
【解决方案2】:

不用仔细看,这个

 s1.toLowerCase();

不会改变s1,而是返回一个new 字符串,它是s1 的小写变体。在 Java 中,字符串是不可变的。所以你需要收集和处理上面返回的值。

【讨论】:

    【解决方案3】:

    您为什么不直接执行以下操作:

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

    【讨论】:

      【解决方案4】:

      字符串是不可变的,因此仅在 String 对象上调用该方法不会更改 String 本身。您应该使用以下内容:

      s1 = s1.toLowerCase();
      s2 = s2.toLowerCase();
      

      【讨论】:

        【解决方案5】:

        您的比较器根本不稳定。

        首先你return -1 如果长度不同。这意味着根据操作数顺序,您可能会发现 "asbd" > "ash" 或相反。

        你也对字符比较做同样的事情。

        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;
        }
        

        使用相同的模式进行长度比较。

        EDITcompare 方法返回-1,意味着您发现第一个操作数小于documentation 中的第二个操作数。

        【讨论】:

          【解决方案6】:

          来自javadoc

          实现者必须确保sgn(compare(x,y)) == -sgn(compare(y,x)) 对所有xy。 (这意味着当且仅当compare(y,x) 抛出异常时,compare(x,y) 必须抛出异常。)。

          这基本上意味着如果您调用 compare(s1,s2) 它必须产生 -1 * compare(s2,s1) 并且您的 return -1; 语句都不会遵循此。取而代之的是,您可以将整数和字符相互比较并返回该值,例如此代码有效(而不是 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 的回答,这是另一个错误。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-29
            • 1970-01-01
            • 2019-06-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-01-09
            • 1970-01-01
            相关资源
            最近更新 更多