This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.

Title

Sorting Collections in Java

Description

<n>This article was originally published on the <a href="http://blogs.encodo.ch/news/view_article.php?id=6"><b>Encodo Blogs</b></a>. Browse on over to see more!</n> <hr> One of the features we expect from a collections library is sorting. You should be able to use generic library mechanisms to sort a list of any kind of element. Most libraries include a generic <c>sort</c> function, to which a comparison functor (object or function pointer) is passed. This functor is called repeatedly on pairs of elements until the list is sorted. Let's define the simple class we'll use in the ensuing examples. <code> class A { String fileName; function getFileName() { return fileName; } } </code> Now, let's sort a <c>List</c>. Is there a <c>sort</c> function on the list object itself? No. Why not? Legacy reasons. In order to avoid breaking existing code, Java has not made any changes to the <c>List</c> interface. Ever. Therefore, you will have to search for any new functionality in the global function unit masquerading as a class<fn> called <c>Collections</c>. There are two sorting functions defined in this class, shown below: <code> public static <t>> void sort(List<t> list); public static <t> void sort(List<t> list, Comparator c); </code> Neither one of these is exactly easy on the eyes and both include the wildcard (?) operator in their definitions. The first version accepts a <c>List<t></c> only if T extends <c>Comparable</c> directly or a generic instantiation of <c>Comparable</c> which takes T or a superclass as a generic parameter. The second version takes a <c>List<t></c> and a <c>Comparator</c> instantiated with T or a supertype. With our simple class <c>A</c> above, it would be pretty easy to implement the interface to give the class a standard ordering. Naively, we might add the following: <code> class A <span class="highlight">implements Comparable</span> { String fileName; function getFileName() { return fileName; } <span class="highlight">public int compareTo(Object _o) { return getFileName().compareTo((A) _o.getFileName()); }</span> } </code> The compiler seems pretty happy with it, but actually calling <c>sort()</c> with a <c>List</c> results in a warning: <div class="caution">Type Safety: Unchecked invocation <c>sort(List)</c> of the generic method <c>sort(List<t>)</c> of type <c>Collections</c></div> If you're using Eclipse, your "Quick-Fix" trigger finger is probably getting mighty itchy right now, but let's avoid simply adding a <c>@Suppress</c> directive above this function and try to find out <i>why</i> the class compiles, but the function call has a problem. A quick search through <a href="http://groups.google.com">Google Groups</a> turns up <a href="http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/a7ce99caf585f885/71b2eca6ac9761be">Collections.sort() in Java 5</a>, which reminds us that <iq>[t]he Comparable interface takes a generic parameter</iq>. Adding in the generic argument (as shown below) fixed the problem and gets rid of the warning. <code> class A implements Comparable<span class="highlight"></span> { ... public int compareTo(<span class="highlight">A</span> _o) { return getFileName().compareTo(_o.getFileName()); } } </code> On top of that, the generic version of <c>Comparable</c> allows us to declare a type-specific <c>compareTo</c> function and get rid of the ugly cast. All's well that ends well, but it would be much nicer if the compiler could tell us that we are misusing <c>Comparable</c> than to have to find out from some guy in a newsgroup. <hr> <ft>This class has a private constructor and cannot be instantiated---you can only use it for its static functions.</ft> <n>Using Java 1.5</n>