3

I want to sort objects by a string they have. Just wondering does this make sense? Before now I have only used Arrays.sort(BlahList); But now I could have many objects and not just an arraylist of strings.

public class Contact implements Comparable
{
    private string name;

    public compareTo (Contact Contact1)
    {
        return this.name.compareTo(Contact1.name);
    }
}

and in the main method I have:

Collections.sort(ContactList);

I would also like to know if this would work for integers if the name was age?

blackpanther
  • 10,998
  • 11
  • 48
  • 78
Andrea
  • 53
  • 2

4 Answers4

2

Firstly, you should type the Comparable interface:

public class Contact implements Comparable<Contact>

Secondly, you should use leading lowercase for your parameters/variables:

public compareTo (Contact contact)

Thirdly, prefer not using this. unless necessary - it's just code clutter:

return name.compareTo(contact.name);

And finally, yes, you can compare age like this:

return age - contact.age; // order youngest to oldest

Or the cleaner way (thanks for pointing this out JB):

return Integer.compareTo(age, contact.age);

This whole class should look like this:

public class Contact implements Comparable<Contact> {
    private string name;

    public int compareTo(Contact contact) {
        return name.compareTo(contact.name);
    }
}

Note: You were missing the return type int from the code for your compareTo() method.

To compare age instead, replace the compareTo() method with this:

public int compareTo(Contact contact) {
    return Integer.compareTo(age, contact.age);
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 1
    For int comparisons that work whatever their value is, you should prefer `Integer.compare(i1, i2)` (which is also clearer) – JB Nizet May 13 '13 at 14:34
  • btw, minus operator may work incorrectly when `age` is around Integer.MAX_VALUE or/and `contact.age` is about `Integer.MIN_VALUE`. Not the case for ages, of course. I recommend use `Integer.compare` (Java7) – RiaD May 13 '13 at 14:34
  • @RiaD I don't particularly care if it throws an NPE on name: this code is more for illustration than production use. – Bohemian May 13 '13 at 14:38
  • @RiaD Are you serious snout age being near MIN/MAX int??? Because that is insane. We are talking about *people* here - the class is called "Contact". I am quite sure age will not be anything larger than around 100. That is the most ridiculous objection I've ever seen. – Bohemian May 13 '13 at 14:41
  • That's why I've add that it isn't the case for ages(they are never negative at least) , but I guess it's good to know that the problem is possible, especially when it's so easy to avoid it. (with just one standard function). I'm sure you know it. But not all people who read your answer. One may start sort any integers this way. I hope i didn't hurt you – RiaD May 13 '13 at 14:44
  • @JBNizet I'll accept cleaner (maybe - only because it would be a good habit to follow), but not safer: Subtracting the age of one person from another isn't going to cause an overflow, is it... – Bohemian May 13 '13 at 14:45
  • What imports are needed? – Andrea May 13 '13 at 14:47
  • You shouldn't need to import anything. Comparable is in `java.lang` package, which is implicitly imported. – Bohemian May 13 '13 at 14:50
  • public class Contact implements Comparable //after this it says interface expected here – Andrea May 13 '13 at 14:53
  • You were missing a return type for the `compareTo()` method. See my edited answer for complete code. Copy paste it into your IDE. – Bohemian May 13 '13 at 14:59
  • @Bohemian: agreed for this particular case. But I explicitely said: "For int comparisons that work whatever their value is". I prefer recommending a comparison technique that is clear and always works, rather than one which is less clear and doesn't always work. The OP is likely not aware that using a subtraction could cause bugs with very large integers, and could apply the same technique on another use-case. Also: it's Integer.compare(), not Integer.compareTo(). And I didn't downvote if that's what you're concerned about. – JB Nizet May 13 '13 at 14:59
  • Its ok, turns out I named my class Comparable and java did not like this..thanks! – Andrea May 13 '13 at 15:01
  • @JBNizet No, not worried - I know you are more noble than to downvote :) Also, I added your suggestion to the code and gave you a little mention. Merci pour tout :) – Bohemian May 13 '13 at 15:04
  • Btw if I wanted the option of letting the user select either to sort by name or age would this be hard to do? Also change from compareTo to compare for the new way :) – Andrea May 13 '13 at 15:12
  • No, it wouldn't be hard. Pass an anonymous implementation of a suitable `Comparator` to the Collection.sort()( method. – Bohemian May 13 '13 at 15:16
0

it works for all. if it is int u need to write following code in compareTo method

return this.age-contact1.age// for ascending order contact1.age-this.age // for descending order

Nagaraju Badaeni
  • 890
  • 8
  • 14
0

If you want multiple comparators then I would suggest you to use Comparator interface:

For Name compare:

public class NameCompare implements Comparator<Contact> {

    @Override
    public int compare(Contact a, Contact b) {
        if (a.getName().compareToIgnoreCase(b.getName())>0)
            return 1;
        else if (a.getName().compareToIgnoreCase(b.getName())<0)
            return -1;
        return 0;
    }
} 

For Age Compare:

public class AgeCompare implements Comparator<Contact> {

        @Override
        public int compare(Contact a, Contact b) {
            if (a.getAge() > b.getAge())
                return 1;
            else if (a.getAge() < b.getAge())
                return -1;
            return 0;
        }
    } 

And in the main, you just pass the desired Comparator:

ArrayList al = new ArrayList<Contact>

Collections.sort(al, new NameCompare())

Collections.sort(al, new AgeCompare())
Ravi Trivedi
  • 2,340
  • 2
  • 14
  • 20
  • why you ever call function twice and do some if's even when function return value you want:) – RiaD May 13 '13 at 14:48
  • @RiaD, what do you mean ? – Ravi Trivedi May 13 '13 at 14:49
  • you may just return `a.getName().compareToIgnoreCase(b.getName());` in first case. It's much cleaner – RiaD May 13 '13 at 14:50
  • @RiaD, The reason I am returning 1,-1,0 because if you want to reverse the order it will easy. Because it clearly tells you what order asc/desc you are returning. Sometime, more code means more clarity :) – Ravi Trivedi May 13 '13 at 14:55
0

In java 7 you can use Integer.compare(age, contact.age). Its (almost) same as (x < y) ? -1 : ((x == y) ? 0 : 1); but much more readable (Integer.compare does not say it will return those exact numbers, but Oracle's implementation will, it could return any other positive instead of 1 and negative instead of -1)

btw. DON't use age-contact.age, beacause Integer.MIN_VALUE-Integer.MAX_VALUE = 1

For complex comparators (eg. first by name then by age if name is equal) I suggest use some library like google guava.

Alpedar
  • 1,314
  • 1
  • 8
  • 12