Jack
Jack

Reputation: 115

Sorting array given two comparators?

Say I have two comparators, a primary and a secondary. How can I sort an array first by the primary comparator, then by the secondary?

Say each object has a name and a number field.

Like

Bob 1
Bob 2
Jack 1
Jack 2

Is it possible without creating a new comparator?

Upvotes: 9

Views: 5520

Answers (3)

Nayuki
Nayuki

Reputation: 18533

Yes, you can accomplish your sort without creating a new comparator.

There is a well-known trick for sorting by a primary field, secondary, tertiary, etc: First sort by the least important field (tertiary), then the next important field (secondary), and finally the most important field (primary). But the sorting algorithm needs to be stable for this to work.

If you are sorting an array, use Arrays.sort(). If you are sorting a List, use Collections.sort(). Both of these methods are guaranteed to be stable.

Suppose your primary comparator object is stored in the variable primaryComp, and your secondary is in secondaryComp. Then here is some code to accomplish what you want:

Arrays.sort(mylist, secondaryComp);  // This must come first!
Arrays.sort(mylist, primaryComp);

Upvotes: 14

Nafiul Islam
Nafiul Islam

Reputation: 82440

Compare the second comparator first, and then the first comparator. I believe that should do the trick. You can create a class to do so.

class FullName {
    public String firstName;
    public String secondName;
}

Say you create a new name, called BobBobbins, assign values and then simple compare the second name first, and then the first name. You can have a static function to do the comparing:

public static bool compareTo ( FullName name1, FullName name2 ) {
    // Algorithm here
}

Should you use a static comparator, you can will have to do this : FullName.compareTo( BobBobbins, CharlieChaplin );

Upvotes: -1

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 135992

assuming your class is

class X {
    String name;
    int num;
}

then sorting will be

Arrays.sort(x, new Comparator<X>() {
        @Override
        public int compare(X o1, X o2) {
            if (o1.name.equals(o2.name)) {
                return Integer.compare(o1.num, o2.num);
            }
            return o1.name.compareTo(o2.name);
        }});

Upvotes: 7

Related Questions