0

I have an ArrayList like this:

ArrayList<Person> list;

The Person type can have a name and a number, both as Strings. I am looking to sort the number strings (not the name) in descending order using the expression below:

Collections.sort(somelist, Collections.reverseOrder());

How can I specify that I want to sort by the number field?

I can get the number by Person.getNumber();

Clone
  • 3,378
  • 11
  • 25
  • 41

2 Answers2

3

You may need this.

Collections.sort(list, 
            Comparator.comparingInt((Person p) -> Integer.valueOf(p.getNumber())).reversed());

If we need to sort both with other fields, then the following would be helpful.

Collections.sort(list, 
            Comparator.comparingInt((Person p) -> Integer.valueOf(p.getNumber()))
            .thenComparing(p -> p.getName()).reversed());
Preston
  • 180
  • 9
  • This is not a stable sort .. if two people have different names but same number the order can flip around. need to add `thenComparing(p.getName())` – Mr R Mar 17 '21 at 05:40
  • That right, but the question is only asked for comparing by the number. – Preston Mar 17 '21 at 05:48
0

The example you gave is using the reverse() method, which gives a Comparator<Person> when passed to Collections.sort() in this case is defined to reverse the natural order of a Comparable<Person>. SO your Person class must implement Comparable<Person> - although unfortunately this is not detected at compile timne (but this requirement is described in the javadoc).

So to order by anything (single or multiple fields), you can either implement the Comparable<Person> interface, or something can implement Comparator<Person> - like in this previously asked on SO question Collections.sort with multiple fields.

Generally you should implement a stable comparison (Stable sort - do we really need it?) - i.e. what happens if two objects have the same number but different names - how do they get sorted? If you don't get the same relative position (a before b or b after a) when giving two inputs, but in different orders then it's not stable, and you won't necessarily get the same results each time you sort (if one of the values is a dupe). So here's the old school way of doing the compare method (assuming you can't have null references in your data).

public int compare(final Person a, final Person b) {
  final int comp = a.getNumber().compareTo(b.getNumber());
  if (0 == comp) {
    return a.getName().compareTo(b.getName());
  }
  return comp;
}

And here's a lambda style example including creating a Comparator (HT @Preston) -

Collections.sort(list, 
            Comparator.comparingInt((Person p) -> Integer.valueOf(p.getNumber()))
            .thenComparing(p -> p.getName()).reversed());
Mr R
  • 754
  • 7
  • 19