Java中针对字符串和整数参数的compareTo方法

3

我正在实现冒泡排序算法,希望它能够接受整数字符串参数。我将所有输入强制转换为字符串,并使用compareTo方法将整数强制转换为字符串进行比较。但是,当使用compareTo比较强制转换后的整数时,得到了错误的答案。我做错了什么?

7个回答

8

Integer.compareTo会按照数字大小对数字进行排序。这正是您想要的。

String.compareTo会按字典顺序对字符串进行排序;也就是按字母顺序排列。

我记得在Windows 3.1中,我的数码相机照片文件夹的排序方式是这样的:PHOTO1、PHOTO10、PHOTO100、PHOTO2、PHOTO20、PHOTO3等等。而Windows XP则更像您所期望的排序方式:PHOTO1、PHOTO2、PHOTO3等等。这是因为它有专门针对表示数字的字符串的排序规则。

在字典顺序中,将一个字符串A中的每个字符与另一个字符串B中的相应字符进行比较。对于两个字符串中的每个相应字符:

  • 如果A的当前字符在字典上小于(在字母表中出现在)B的字符,则A在B之前。
  • 如果B的字符小于A的字符,则B在A之前。
  • 如果两个字符相同,则我们还不知道。下一个字符将被检查。
  • 如果其中一个字符串已经没有更多的字符了,则较短的那个在前面。
  • 如果两个字符串都没有更多的字符,则它们是相同的字符串。

这里的第四点是为什么您得到错误答案的原因,假设Eddie对您的问题的分析是正确的。

考虑字符串"10"和"2"。字典顺序将查看每个字符串的第一个字符,分别为'1'和'2'。在Java使用的字符集中,字符'1'在字符'2'之前,因此它将"10"排序在"2"之前,就像"bare"在"hare"之前排序一样,因为'b'在'h'之前。

我建议您在排序之前将字符串转换为整数。使用Integer.parseString来完成这个操作。


将字符串转换为整数对我来说听起来更合理。当然,这只有在所有字符串实际上都是整数的字符串表示时才有效。 - Alan Moore
漂亮的答案,附有精美示例。 - Kanagavelu Sugumar

2

您确定要在同一列表中混合整数和字符串吗?如果是这样,整数是小于还是大于字符串?这个特定的排序标准是什么?

您也可以创建一个冒泡排序方法,对不同的整数列表和字符串列表(以及任何其他类别的列表)进行排序。为此,您可以使用泛型。例如:

public static <T> void bubbleSort(List<T> elements, Comparator<T> comparator) {
    // your implementation
}

您可以使用comparator参数来比较elements,因此它们可以是整数或字符串(但不能同时为两者)。编译器不会让您(没有任何警告)传递一个类的对象列表和另一种类的比较器,因此比较始终有效。


0

这是因为在String类中的以下Java API代码只比较两个字符串中最小长度的字符。

public int compareTo(String anotherString) {
    int len1 = value.length;
    int len2 = anotherString.value.length;
    int lim = Math.min(len1, len2); //**HERE**
    char v1[] = value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}

如果我们使用这个 API 进行比较
String first = "ABCD"; 
String second = "ABZ"; 
System.out.println("" + "ABCD".compareTo("ABZ")); //-23

将返回负值,表示ABCD小于ABZ,意味着第一个字符串中的C小于Z并忽略了D。

因此,我们可能需要类似下面的内容

class StringNumericComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        int len1 = o1.length();
        int len2 = o2.length();
        if(len1 != len2) {
            return len1 - len2; //Else iterate all diff lengh chars and SUM it.
        }
        int lim = Math.min(len1, len2);
        char v1[] = o1.toCharArray();
        char v2[] = o2.toCharArray();

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return 0;
    }
}

0

你所描述的并不是真正可能的...也许你需要发布代码。这是我对你正在做的事情的解释:

public int compareTo(final Object o)
{
    final String str;

    str = (String)o; // this will crash if you pass it an Integer.

    // rest of the code.
}

compareTo的文档在这里,你真的应该遵循合同。


0

首先,你需要使用Comparator而不是Comparable,因为Comparator接受两个对象,而Comparable将当前对象与传递的一个对象进行比较,并且你无法更改String或Integer上的compareTo()方法,所以:

public class CompareIntegersAsStrings implements Comparator {
  public int compare(Object o1, Object o2) {
    return o1.toString().compareTo(o2.toString());
  }
}

1
这将失败,因为“10”小于“2”。 - Lawrence Dol
这是我的理解:他想将整数作为字符串进行比较。如果他想要自动将字符串转换为整数并按数字进行比较,那当然是不同的。 - cletus

0
假设您的意思是将整数转换为字符串,然后进行比较,那么这种方法是行不通的。例如,假设您有整数123412。如果您将它们转换为字符串并进行比较,您将得到以下顺序:
1
1234
2

这是针对ASCII排序正确但数字排序不正确的情况。也就是说,我假设你的代码做了类似于这样的事情:

public int myCompare(Integer a1, Integer a2) {
    myCompare(String.valueOf(a1), String.valueOf(a2));
}

public int myCompare(String a1, String a2) {
    ....
}

为什么我这样假设呢?因为你在谈论得到了错误的结果,而没有提到出现异常。如果你实际上出现了异常,那么其他帖子中的回答是正确的,强制类型转换是行不通的。

0

创建一个Comparable的实例。

字符串无法直接转换成整数,并且没有比较方法。


"comparryo" 是一个打错的单词。如果你把结尾的 "ry" 往左移一格,就会变成 "et",这样就得到了 "compareto"。 - Eddie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接