views:

4539

answers:

8

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?

+6  A: 

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 A
+1  A: 

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
already edited my message to mention SortedSet ;)
Yuval A
+4  A: 
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
+3  A: 
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
Specifically typing this Comparator may be unnecessary as the asker simply wants to compare two objects by toString. It seems to me like the type may be unnecessary.
Nathan Feger
@Nathan. Yes, the generic type doesn't need to be any more specific than Object. You don't have to define the comparator inline like I have either.
Dan Dyer
+2  A: 

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
+2  A: 

I would do something very similar to Pierre:

public class Foo implements Comparable {

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.

psykotedy
+2  A: 

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/

Mario Fusco
Awesome, I had never heard of lambdaj, but I can immediately see how useful it can be.
instanceofTom
Hey just wanted to let you know that I am using lambdaj in a new project and it is working nicely. Thanks again.
instanceofTom
If you are an happy lambdaj user could be great if you will add yourimpressions here. Thanks :)http://code.google.com/p/lambdaj/wiki/WhoIsUsingLambdaj
Mario Fusco
+2  A: 

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