用于字符串和整数参数的 Java compareTo

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/900745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:17:00  来源:igfitidea点击:

Java compareTo for String and Integer arguments

javacompareto

提问by Iain Samuel McLean Elder

I am implementing the bubble sort algorithm and I want it to be able to accept both Integerand Stringparameters. I cast all input as Strings and use the compareTomethod to compare the integers casted as strings to the strings. I am getting an incorrect answer when using compareToto compare the casted integers. What am I doing wrong?

我正在实现冒泡排序算法,我希望它能够同时接受IntegerString参数。我将所有输入转换为字符串,并使用该compareTo方法将转换为字符串的整数与字符串进行比较。compareTo用于比较转换的整数时,我得到了不正确的答案。我究竟做错了什么?

回答by Iain Samuel McLean Elder

Integer.compareTo sorts numbers numerically. This is what you want.

Integer.compareTo 按数字对数字进行排序。这就是你想要的。

String.compareTo sorts strings lexicographically; that is, in alphabetical order.

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

I remember in Windows 3.1 that the folder of photos from my digital camera was ordered like this: PHOTO1, PHOTO10, PHOTO100, PHOTO2, PHOTO20, PHOTO3, ... and so on. Windows XP sorts them more like you would expect: PHOTO1, PHOTO2, PHOTO3, ... etc. This is because it has special sorting rules for strings that represent numbers.

我记得在 Windows 3.1 中,我的数码相机中的照片文件夹是这样排序的:PHOTO1、PHOTO10、PHOTO100、PHOTO2、PHOTO20、PHOTO3……等等。Windows XP 更像您期望的那样对它们进行排序:PHOTO1、PHOTO2、PHOTO3 等。这是因为它对表示数字的字符串有特殊的排序规则。

In lexicographical ordering, each character in one string A is compared to the corresponding character in another string B. For each corresponding character in the two strings:

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

  • If A's current character is lexicographically less than (comes before in the alphabet) B's character, then A comes before B.
  • If B's character is less than A's character, then B comes before A.
  • If the two characters are the same, then we don't know yet. The next one is checked.
  • If there are no more characters left in one of the strings, then the shorter one comes before the longer one.
  • If there are no more character left in both strings, then they are the same string.
  • 如果 A 的当前字符按字典顺序小于(在字母表中排在前面)B 的字符,则 A 排在 B 之前。
  • 如果 B 的字符小于 A 的字符,则 B 在 A 之前。
  • 如果这两个字符相同,那么我们还不知道。检查下一个。
  • 如果其中一个字符串中没有更多字符,则较短的字符排在较长的字符之前。
  • 如果两个字符串中都没有剩余字符,则它们是相同的字符串。

The fourth point here is why you are getting incorrect answers, assuming Eddie's analysis of your problem is correct.

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

Consider the strings "10" and "2". Lexicographical ordering would look at the first characters of each, '1' and '2' respectively. The character '1' comes before '2' in the character set that Java uses, so it sorts "10" before "2", in the same way that "bare" is sorted before "hare" because 'b' comes before 'h'.

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

I suggest you cast your strings to integers before sorting. Use Integer.parseString to do this.

我建议您在排序之前将字符串转换为整数。使用 Integer.parseString 来做到这一点。

回答by cd1

are you sure you want to mix Integers and Strings in the same list? if so, are Integers less or greater than Strings? what is this particular sorting criteria?

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

you can also make a bubble sort method which sorts distinct lists of Integer and lists of String (and lists of any other class). to do so, you can use Generics. for example:

您还可以创建一个冒泡排序方法,该方法对 Integer 的不同列表和 String 的列表(以及任何其他类的列表)进行排序。为此,您可以使用泛型。例如:

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

you use the comparatorparameter to compare the elements, that's why they can be Integers or Strings (not both at the same time). the compiler won't let you [without any warning] pass a list of objects of one class and a comparator of a different class, so the comparison will always work.

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

回答by Kanagavelu Sugumar

It is because of the below java API code in Stringclass where minimum length of chars among the two string are only compared.

这是因为类中的以下 java API 代码String仅比较两个字符串之间的最小字符长度。

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

If we use this api to compare

如果我们用这个api来比较

String first = "ABCD"; 
String second = "ABZ"; 
System.out.println("" + "ABCD".compareTo("ABZ")); //-23

will return negative value saying ABCD is less than ABZ means C is less than Z and ignored D in the first String.

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

So maybe we need something like below

所以也许我们需要像下面这样的东西

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

回答by Jeremy Huiskamp

Take an instance of Comparable.

举个例子Comparable

Strings can't really be cast to integers, and there is no comparryo method.

字符串不能真正转换为整数,并且没有比较方法。

回答by TofuBeer

What you describe isn't really possible... so perhaps you need to post the code. Here is my interpretation of wht you are doing:

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

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

The documentation for compareTo is here, you really should follow the contract.

compareTo 的文档在这里,您确实应该遵守合同。

回答by cletus

Firstly you want Comparatornot Comparablebecause Comparator takes two objects whereas Comparable compares the current object to one passed in and you can't change the compareTo() method on String or Integer so:

首先,您希望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());
  }
}

回答by Eddie

Assuming that what you really mean is that you are converting Integers to Strings, and then comparing, this will not work. For example, let's say you have the Integer 1234and the Integer 1and the Integer 2. If you convert these to Strings and compare them, you will get the order:

假设您真正的意思是将整数转换为字符串,然后进行比较,这将不起作用。例如,假设您有 Integer1234和 Integer1和 Integer 2。如果将这些转换为字符串并进行比较,您将得到以下顺序:

1
1234
2

which is correct for ASCII sorting and incorrect for numeric sorting. That is, I assume your code does something like this:

这对于 ASCII 排序是正确的,对于数字排序是不正确的。也就是说,我假设您的代码执行以下操作:

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

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

Why do I assume this? Because you are talking about getting an incorrect result and not talking about getting Exceptions. If you are actually getting Exceptions, then the other posters are correct that casting will not work.

为什么我会这样假设?因为您在谈论获得不正确的结果而不是在谈论获得异常。如果您实际上遇到了例外情况,那么其他海报是正确的,即投射将不起作用。