26

Assume I have a user defined Java class called Foo such as:

public class Foo 
{

    private String aField;

    @Override
    public String toString()
    {
        return aField;
    }

}

And a Collection such as:

List<Foo> aList;

What I am looking to do is to sort the List alphabetically based upon each member's returned '.toString()' value.

I have tried using the Collections.sort() method, but the result was not what I was attempting. What do I need to do inorder to accomplish this?

double-beep
  • 5,031
  • 17
  • 33
  • 41
Tom Neyland
  • 6,860
  • 2
  • 36
  • 52

10 Answers10

70
Collections.sort(fooList,
                 new Comparator<Foo>()
                 {
                     public int compare(Foo f1, Foo f2)
                     {
                         return f1.toString().compareTo(f2.toString());
                     }        
                 });

Assuming that toString never returns null and that there are no null items in the list.

Dan Dyer
  • 53,737
  • 19
  • 129
  • 165
20

google-collections makes this really easy with Ordering:

Collections.sort(list, Ordering.usingToString());

Is bringing in a whole 3rd-party library just to use something you could write trivially using a Comparator (as others have provided) worthwhile? No, but google-collections is so cool you'll want to have it anyway for a bunch of other reasons.

On the sorting front, you can also easily do things like reversing:

Ordering.usingToString().reverse();

or break ties:

Ordering.usingToString().compound(someOtherComparator);

or deal with nulls:

Ordering.usingToString().nullsFirst();

etc., but there's a bunch more stuff in there (not just sorting-related, of course) that leads to really expressive code. Check it out!

Cowan
  • 37,227
  • 11
  • 66
  • 65
18

Use the API sort(List list, Comparator c)which specifies a comparator, and implement is as you wish.

Alternatively, if you do not specifically need a List, use a SortedSet, same goes with the comparator.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
7
public class Foo
   implements Comparable<Foo>
{

    private String aField;

    public Foo(String s)
       {
       aField=s;
        }


    public String getAField()
        {
        return aField;
        }

   public int compareTo(Foo other)
        {
        return getAField().compareTo(other.getAField());
        }


    @Override
    public String toString()
    {
    return getAField();
    }

}

and then

Collections.sort(list);

Pierre
  • 34,472
  • 31
  • 113
  • 192
6

The Java 8 version:

list.sort(Comparator.comparing(Object::toString));

Or streaming:

List<Foo> sortedList = unsortedList
    .stream()
    .sorted(Comparator.comparing(Object::toString)))
    .collect(Collectors.toList());
David Leppik
  • 3,194
  • 29
  • 18
5

I would do something very similar to Pierre:

public class Foo implements Comparable<Foo>
{
    private String aField;

    @Override
    public String toString()
    {
        return aField;
    }

    public int compareTo(Foo o)
    {
        return this.toString().compareTo(o.toString());
    }
}

Then, like Pierre, I would use Collections.sort(list) as Pierre suggests.

RAS
  • 8,100
  • 16
  • 64
  • 86
psykotedy
  • 81
  • 3
3

lambdaj allows you to sort, filter and in general manipulate collections without writing loops or obscure inner classes. For example the sorting you were asking can be achieved as it follows:

sort(foos, on(Foo.class).toString());

If you are interested in it check it out at:

http://code.google.com/p/lambdaj/

sth
  • 222,467
  • 53
  • 283
  • 367
Mario Fusco
  • 13,548
  • 3
  • 28
  • 37
  • Awesome, I had never heard of lambdaj, but I can immediately see how useful it can be. – Tom Neyland Sep 09 '09 at 15:46
  • Hey just wanted to let you know that I am using lambdaj in a new project and it is working nicely. Thanks again. – Tom Neyland Oct 19 '09 at 17:53
  • If you are an happy lambdaj user could be great if you will add your impressions here. Thanks :) http://code.google.com/p/lambdaj/wiki/WhoIsUsingLambdaj – Mario Fusco Oct 19 '09 at 22:12
3

I would strongly advise you to only use toString for debugging purposes... however... to expand on what Yuval A wrote above...

public class X
    implements Comparator
{
    public int compare(final Foo a, final Foo b) 
    {
        return (a.toString().compareTo(b.toString()));
    }
}

However you really should have Foo implement Comarable or write a proper Compartor that does not make use of toString.

TofuBeer
  • 60,850
  • 18
  • 118
  • 163
1

If you want the collection to remain sorted, rather than sorting it at specific points, you could put it in a TreeSet with a defined Comparator. Otherwise, I'd use the Collections.sort method already mentioned by Yuval.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
0

Sort ArrayList on POJO int property (Ascending or Descending):

Collections.sort(myPojoList, (a, b) -> a.getId() - b.getId()); //ASC
Collections.sort(myPojoList, (a, b) -> b.getId() - a.getId()); //DESC

//Alternatively use Integer.compare()
Collections.sort(myPojoList, (a, b) -> Integer.compare(a.getId(), b.getId())); //ASC
Collections.sort(myPojoList, (a, b) -> Integer.compare(b.getId(), a.getId())); //DESC

Sort ArrayList on POJO String property:

Collections.sort(myPojoList, (a, b) -> a.getName().compareTo(b.getName())); //ASC
Collections.sort(myPojoList, (a, b) -> b.getName().compareTo(a.getName())); //DESC

Sort ArrayList on POJO Boolean property:

Collections.sort(myPojoList, (a, b) -> Boolean.compare(a.isMale(), b.isMale())); //ASC
Collections.sort(myPojoList, (a, b) -> Boolean.compare(b.isMale(), a.isMale())); //DESC

Extra: get distinct ArrayList

myPojoList= new ArrayList<>(new LinkedHashSet<>(myPojoList)); //Distinct
Pierre
  • 8,397
  • 4
  • 64
  • 80