deejay
deejay

Reputation: 575

Sorting in Collections Comparator/Comparable

I am trying to sort the Person reverse alphabetically by name and then sorting in ascending order by age

I could sort in reverse order of name, but unable to sort again in ascending order of age.

PerId Name Age
--------------
7   Simpson 8
3   Michel  10
9   Mark    35
2   Mark    30
8   Lee     40
1   Jorge   19
5   Frank   28
6   Bill    34
4   Bill    16

My Code

class Util {
    public static List<Person> getPersons() { 
        List<Person> col = new ArrayList<Person>(); 
        col.add(new Person(5, "Frank", 28)); 
        col.add(new Person(1, "Jorge", 19)); 
        col.add(new Person(6, "Bill", 34)); 
        col.add(new Person(3, "Michel", 10)); 
        col.add(new Person(7, "Simpson", 8)); 
        col.add(new Person(4, "Bill",16 )); 
        col.add(new Person(8, "Lee", 40)); 
        col.add(new Person(9, "Mark", 35));
        col.add(new Person(2, "Mark", 30)); 
        return col; 
    } 
}

class Person implements Comparator<Person> { 
    private int perId; 
    private String name; 
    private int age;

    public Person(){}

    public Person(int perId, String name, int age) {
        this.perId = perId;
        this.name = name;
        this.age = age;
    }

    //.... getters/setters

    @Override
    public int compare(Person e1, Person e2) {
        return e2.getName().compareTo(e1.getName());
    }
}

class PersonId implements Comparable<Person>{
    private Integer perId;

    @Override
    public int compareTo(Person o) {
        return this.perId.compareTo(o.getPerId());
    }
    //...getter
}

public class TestPersonSort {
    public static void main(String[] args) {
        List<Person> coll = Util.getPersons(); 
        Collections.sort(coll, new Person()); 
        // sort method 
        printList(coll);

        //problem here ***********************************************
        //Collections.sort(coll); 
    } 
    private static void printList(List<Person> list) { 
        System.out.println("PerId\tName\tAge"); 
        for (Person e: list) { 
            System.out.println(e.getPerId() + "\t" + e.getName() + "\t" + e.getAge()); 
        }
    }
}

Upvotes: 0

Views: 121

Answers (2)

Nathan
Nathan

Reputation: 8971

An easy way is to have Person implement Comparable<Person>. main() can then use Collections.sort(coll);

class Person implements Comparable<Person> { 
    private int perId; 
    private String name; 
    private int age;

    public Person(){}

    public Person(int perId, String name, int age) {
        this.perId = perId;
        this.name = name;
        this.age = age;
    }

    //.... getters/setters

    @Override
    public int compareTo(Person other) {
        int result;

        if (other == null)
            return(0);

        if (other == this)
            return(0);

        result = name.compareTo(other.name);

        if (result != 0)
            return(-result);    // Sort names in reverse

        return(age - other.age);   // Sort age ascending
    }
}

Upvotes: 0

rgettman
rgettman

Reputation: 178333

Have a Comparator class first compare the person's name. If the comparison is not 0, return it. If it is 0, then move on to compare the person's age.

public int compare(Person e1, Person e2) {
    int comp = e2.getName().compareTo(e1.getName());  // desc
    if (comp != 0) return comp;
    return e1.getAge() - e2.getAge();  // asc
}

Another option, a bit more complicated, but more flexible, is to have a Comparator that uses other Comparators. Then you can supply Comparator<Person>s that compare one attribute each, in a List, to combine their effects.

public class FlexiblePersonComparator implements Comparator<Person>
{
   private List<Comparator<Person>> comparators;

   public FlexiblePersonComparator(List<Comparator<Person>> comparators)
   {
      this.comparators = comparators;
   }

   @Override
   public int compare(Person p1, Person p2)
   {
      int comp;
      for (Comparator<Person> comparator : comparators)
      {
         comp = comparator.compare(p1, p2);
         if (comp != 0)
            return comp;
      }
      return 0;
   }
}

Upvotes: 2

Related Questions