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.