You need to reverse the effects of a Comparator. You
need to return less than when this Comparator returns greater than, and greater
than when it returns less than.
Use ReverseComparator
to reverse the effects of a Comparator. Supply an existing Comparator to the constructor of ReverseComparator, and it reverses the effects
of that Comparator. The following
example demonstrates the use of ReverseComparator to reverse the result of a
custom MyComparator instance:
Comparator myComparator = new MyComparator( );
Comparator reverseComparator = new ReverseComparator( myComparator );
Book book1 = new Book( );
Book book2 = new Book( );
int comparison = myComparator.compare( book1, book2 );
int reversedComparison = reverseComparator( book1, book2);
The value of reversedComparison
is simply the negative of comparison;
if MyComparator decides that book1 is less than book2, the ReverseComparator returns the opposite
result—greater than. ReverseComparator simply wraps the original
Comparator and multiplies the result
by negative one.
Example 4-1 is an
implementation of a Comparator that
is reversed using the ReverseComparator. This BookComparator compares two Book objects by the name and author bean properties. Sorting a list of
books using this Comparator results
in a list sorted alphabetically by book name and author name; if two
books have the same name, they are sorted by author name.
Example 4-1. A Comparator that compares Book objects by name and author
package com.discursive.jccook.collections.compare;
import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.collections.comparators.ReverseComparator;
public class BookComparator implements Comparator {
public int compare(Object o1, Object o2) {
int comparison = -1;
if( o1 instanceof Book && o2 instanceof Book ) {
Book b1 = (Book) o1;
Book b2 = (Book) o2;
String b1Name = b1.getName( );
String b2Name = b2.getName( );
String b1Author = b1.getAuthor( );
String b2Author = b2.getAuthor( );
if( StringUtils.isNotEmpty( b1Name ) &&
StringUtils.isNotEmpty( b2Name ) ) {
comparison = b1Name.compareTo( b2Name );
}
if( comparison == 0 &&
StringUtils.isNotEmpty( b1Author ) &&
StringUtils.isNotEmpty( b2Author ) ) {
comparison = b1Author.compareTo( b2Author );
}
}
return comparison;
}
}Example 4-2 sorts an array of
Book objects in reverse order.
Example 4-2. Using ReverseComparator to sort Book objects
package com.discursive.jccook.collections.compare;
import java.util.*;
import org.apache.commons.collections.comparators.ReverseComparator;
public class ReverseExample {
public static void main(String[] args) throws Exception {
ReverseExample example = new ReverseExample( );
example.start( );
}
public void start( ) throws Exception {
// Create a Reversed BookComparator
Comparator bookCompare = new BookComparator( );
Comparator reverseComparator = new ReverseComparator( bookComparator );
// Create a List of Book objects
List books = new ArrayList( );
Book book1 = new Book( );
book1.setName( "TitleA" );
book1.setAuthor( "John" );
books.add( book1 );
Book book2 = new Book( );
book2.setName( "TitleB" );
book2.setAuthor( "Donald" );
books.add( book2 )
Book book3 = new Book( );
book3.setName( "TitleA" );
book3.setAuthor( "Doug" );
books.add( book3 );
// Sort the List of Book objects with the Reversed BookComparator
Collections.sort( books, reverseComparator );
}
}After Collections.sort( ), the
books array is sorted in reverse
alphabetical order by book name and author name: "TitleB by Donald"
followed by "TitleA by John" followed by "TitleA by Doug."
If you were using a simple Comparator to sort an array, you could sort
and reverse the resulting array with Arrays.reverse( ), or you could reverse a
List with Collections.reverse( ). Wrapping a Comparator in ReverseComparator may help you avoid the call
to reverse( ), but the benefit is
miniscule. ReverseComparator makes
more sense when used in the context of a ChainedComparator; see Recipe 4.4 for more information
about the ChainedComparator.
Note that use of StringUtils.isNotEmpty(
) is used in BookComparator
to check if either of the bean properties are null or blank. This
utility,
is
from StringUtils, and it is
introduced in Recipe
2.2.
