tags:

views:

1829

answers:

7

I am building a bubble sort and I want it to be able to accept both Integer and String parameters. I cast all input as Strings and use the compareto method to compare the integers casted as strings and the strings. I am getting some incorrect answer when using compareto to compare the casted integers. What am I doing wrong?

A: 

Take an instance of Comparable.

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

Jeremy Huiskamp
"comparryo" was a typo. If you move the "ry" at the end one key to the left, you get "et" which gives you "compareto".
Eddie
A: 

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.

TofuBeer
A: 

Firstly you want Comparator not Comparable because 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:

public class CompareIntegersAsStrings implements Comparator {
  public int compare(Object o1, Object o2) {
    return o1.toString().compareTo(o2.toString());
  }
}
cletus
This will fail because "10" is "less than "2".
Software Monkey
That's how I read the question: he wants to compare integers as strings. If he wants to automatically convert strings to integers and compare them numerically, that is of course different.
cletus
A: 

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 1234 and the Integer 1 and the Integer 2. If you convert these to Strings and compare them, you will get the order:

1
1234
2

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

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.

Eddie
+2  A: 

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:

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

you use the comparator parameter 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.

cd1
+1  A: 

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

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

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.

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:

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

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

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

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

isme
Converting the strings to Integers sounds more reasonable to me, too. Of course, it will only work if all of the strings are in fact string representations of integers.
Alan Moore
A: 

So how would you compare signed integers with such an implementation? I tried Arrays.sort(result,new Comparator() { public int compare(String o1, String o2){ return String.valueOf(o1).compareTo(String.valueOf(o2)); } }); //sort the array in ascending order

but it sorts negative integers incorrectly.

Igor G.