3

I have an arrayList of objects and I want to run a series of sort operations on this list. I would want to sort them by first by name, and if two names are same than sort them by id, for example.

How can i implement it?

This is my code

Comparator<Ticket> mc;
mc = new TicketIdComparator();
Collections.sort(tickets, mc);


final class TicketIdComparator implements Comparator<Ticket>

{

    @Override
    public int compare(Ticket ticket1, Ticket ticket2) {
        String TicketId1 = ((Ticket) ticket1).getNumber();
        String TickedId2 = ((Ticket) ticket2).getNumber();

        int num1=Integer.parseInt(TicketId1);
        int num2 =Integer.parseInt(TickedId2);

        if (num1<num2)
            return 1;
        if (num1>num2)
            return -1;
        return 0;



    }
}

This code sorting list by id, but again i want to sort on name

Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
Romi
  • 4,833
  • 28
  • 81
  • 113

6 Answers6

5

You can write a Comparator from a collection of comparators.

public static <T extends Comparable<T>> Comparator<T> comparatorFrom(final Comparator<T>... comparators) {
    return new Comparator<T>() {
        @Override
        public int compare(T o1, T o2) {
            for (Comparator<T> comparator : comparators) {
                final int cmp = comparator.compare(o1, o2);
                if (cmp != 0) return cmp;
            }
            return 0;
        }
    };
}

// you can then use
Arrays.sort(list, comparatorFrom(comp1, comp2, comp3, comp4));
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I get a warning from Eclipse saying: "Type safety: Potential heap pollution via varargs parameter comparators", should I add `@SafeVarargs` ? – Christophe Roussy Jun 02 '16 at 08:18
  • @ChristopheRoussy That appears to be an IDE specific warning. I would hope Eclipse has a suggested solution like an appropriate \@SuppressWarning – Peter Lawrey Jun 02 '16 at 08:28
  • 1
    Do you mean something like `@SuppressWarnings("unchecked") final Comparator... comparators`, in fact Eclipse suggests multiple solutions. – Christophe Roussy Jun 02 '16 at 08:32
  • @ChristopheRoussy in which case I might follow one of them. IntelliJ doesn't complain and in fact there is no issue IMHO, it's just a matter of keeping your IDE happy. – Peter Lawrey Jun 02 '16 at 08:36
3
  Collections.sort(myList, new Comparator() {

     @Override
     public int compare(Object o1, Object o2)
     {
        // write your ordering code here
        return 0;
     }

  });

Just fill in the code for the comparison you want and Java will handle the sorting for you.

Edit for updated question:

Comparator<Ticket> mc;
mc = new TicketIdComparator();
Collections.sort(tickets, mc);


final class TicketIdComparator implements Comparator<Ticket>

{

    @Override
    public int compare(Ticket ticket1, Ticket ticket2) {
        String TicketId1 = ((Ticket) ticket1).getNumber();
        String TickedId2 = ((Ticket) ticket2).getNumber();

        int num1=Integer.parseInt(TicketId1);
        int num2 =Integer.parseInt(TickedId2);

        if (num1<num2)
            return 1;
        else if (num1>num2)
            return -1;
        else
            return ticket1.getName().compare(ticket2.getName());
    }
}
Jordan Bentley
  • 1,309
  • 1
  • 8
  • 28
  • please look at my edit, this is working for one sort, now what should i do, if i want to perform sorting on the basis of name on this sorted list – Romi Nov 21 '11 at 13:23
2

As you said, and similar as the code you already wrote you would create a class that implements the Comparator interface for Ticket. First, you compare the ticket's names using a String comparator, and if that results in 0 (equal name) then you would compare by id in the same comparator.

Make sure the string comparator does trimming before (remove before and after empty spaces) and maybe ignore casing, that's up to you.

If you want some kind of generalization, then you can write a decorator comparator which calls the more specifics ones. If you want to know more about this, let me know.

Luciano
  • 8,552
  • 5
  • 32
  • 56
  • Luciano: i got the solution from Jordan Bentley, but i think i want a more general solution. as sometimes i want to sort by name, sometimes by summary, sometimes by id....and currently am making separate comparators for each..is there any way, i can do from one comparator. – Romi Nov 22 '11 at 04:40
  • I was going to write the code by then I decided to search :) The first two answers to this question http://stackoverflow.com/questions/1421322/how-do-i-sort-a-list-with-multiple-sort-parameters will help you with the idea of comparing by multiple fields. If you want to do it with an utility library, then take a look at this question: http://stackoverflow.com/questions/6081384/does-anyone-know-of-a-java-comparators-library – Luciano Nov 22 '11 at 12:55
1

With Java 8 you can use lambdas and based on answer by Peter Lawrey you can do something pretty:

        Collections.sort(users, comparatorFrom(

                    (final User u1, final User u2) -> u1.getDomain().getFirstName()
                        .compareTo(u2.getFirstName()),

                    (final User u1, final User u2) -> u1.getLastName().compareTo(u2.getLastName()),

                    ...more comparators here...

               ));
Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
1

Collections.sort(myList, new Comparator() {

 @Override
 public int compare(Object o1, Object o2)
 {
    // write your ordering code here for sorting list by id
    return 0;
 }

});

list with sorted by id

Collections.sort(myList, new Comparator() {

 @Override
 public int compare(Object o1, Object o2)
 {
    // write your ordering code here for sorting list by name
    return 0;
 }

});

it will give list with sorted by name

varsha
  • 304
  • 8
  • 22
0

You need to use a stable sorting algorithm, then sort by ID first and after that sort by name.

Check out this comparison of algorithms to find one that suits your needs.

okrumnow
  • 2,346
  • 23
  • 39
  • No need to sort twice: you can compare both the id and the name (as in the example) in one step. If the ID is the same then compare the names. See Jordan's answer – Matteo Nov 21 '11 at 13:33
  • @Matteo Well, meanwhile there is a lot more information in the question. First version didn't even mention a programming language. There were just sorting of a list by two values, and for that sorting twice in the way i mentioned is a possible solution. – okrumnow Nov 21 '11 at 13:53