Implementing custom compareTo
Asked Answered
N

4

8
@Override
public int compareTo(Object t) 
{
    if(t instanceof Student)
    {
        Student s = (Student)t;
        return (this.name.compareTo(s.name));
    }
    else
        return -1;
}

This is my compareTo method implementation for comparing two Student objects based on their name. Is it possible to compare two such objects based on multiple fields i.e., both name and age?

Nombles answered 12/9, 2013 at 7:15 Comment(0)
C
3

Yes it is possible to compare two objects based on different sort sequences using Comparator interface compare method.

You need to create a sort sequence class. Sorting user defined objects using comparator

Certify answered 12/9, 2013 at 7:16 Comment(2)
Can you also tell me the difference between Collections.sort() and getting a sorted collection by adding into a TreeSet?Nombles
@AnjanBaradwaj, I feel, instead of providing a vague answer, I would like you to ask this question on SO, of course with some efforts and code and we both will learn about it from experts :)Certify
S
16

Yes, but first you should type the Comparable interface you're implementing. Here's what it should look like:

public class Student implements Comparable<Student> {
    private int age;
    private String name;
    @Override
    public int compareTo(Student s) {
        if (name.equals(s.name))
            return age - s.age;
        return name.compareTo(s.name));
    }
}

Notice how with the typed interface Comparable<Student>, instead of the raw type Comparable, there's no need to cast.

Staircase answered 12/9, 2013 at 7:43 Comment(5)
It is considered poor style, because it us "unsafe" (unless you use instanceof, which is also poor style), but it's completely unnecessary in this case if you correctly type this class, which is good style. Your code should use as narrow typing as it can.Staircase
Warning! The code above works well, because age is not supposed to be a negative value. But be careful when negative values ​​are possible. Do not take the above code as the canonical way to implement Comparable<T> (natural ordering)Quatrain
@FernandoPelliccioni actually, this code works perfectly for negative values of age (you can verify this yourself using pen and paper). The only vulnerability introduced by allowing negative numbers is numeric overflow, but to be a problem it requires values in the billions - a situation that is reasonable to ignore for such dara.Staircase
@Bohemian, you're right, I did wrong calculations. Sorry for the noise. However, we should not consider this code as the standard way of writing comparators for integral types.Quatrain
Name is being compared twice. I would prefer: int result = name.compareTo(s.name); if(result==0) return age - s.age; else return result;Shainashaine
C
3

Yes it is possible to compare two objects based on different sort sequences using Comparator interface compare method.

You need to create a sort sequence class. Sorting user defined objects using comparator

Certify answered 12/9, 2013 at 7:16 Comment(2)
Can you also tell me the difference between Collections.sort() and getting a sorted collection by adding into a TreeSet?Nombles
@AnjanBaradwaj, I feel, instead of providing a vague answer, I would like you to ask this question on SO, of course with some efforts and code and we both will learn about it from experts :)Certify
P
1

Note that you are overloading the compareTo method in your above code, not overriding it.

The interface you are implementing:

public interface Comparable<T> {
    public int compareTo(T o);
}

Your implementation:

@Override
public int compareTo(Object t) {
    //...
}

The original author of this interface, Josh Bloch, advised in his book Effective Java to use the @Override annotation just for this reason; bugs caused by overloading can be rather hard to spot.

You say you want to compare these objects "based on multiple fields"- I'm not sure if this means "order them one way based on two fields" or "order them multiple ways, each based on a single field". Either are possible, as demonstrated in the other answers here.

However, this is the bottom line:

You should implement Comparable<T> if you are creating a class yourself, as you appear to be, and want to define a "natural ordering" for this class. If you want to define multiple orderings or you do not control the class in question, define your own ordering in a class that implements Comparator<T> (See here).

Phytophagous answered 27/12, 2014 at 5:33 Comment(0)
A
1

Apache CompareToBuilder class is worth a mention.

You can implement with or without reflection

public int compareTo(Object o) {
    return CompareToBuilder.reflectionCompare(this, o);
}
Aflutter answered 26/3, 2015 at 23:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.