Use ComparatorChain to create a series of Comparator objects that appear as a single
Comparator. A ComparatorChain compares two objects with each
Comparator in the chain until a
Comparator returns a nonzero value.
If a Comparator returns equality
(zero), the ComparatorChain then
moves to the next Comparator to
obtain another comparison. The following example demonstrates the use of
chained BeanComparators; if two
Person objects have the same lastName, the chain created in this example
tries to compare the objects by firstName:
Person person1 = new Person( );
person1.setLastName( "Payne" );
person1.setFirstName( "James" );
person1.setAge( 21 );
Person person2 = new Person( );
person2.setLastName( "Payne" );
person2.setFirstName( "James" );
person2.setAge( 85 );
Person person3 = new Person( );
person3.setLastName( "Payne" );
person3.setFirstName( "Susan" );
person3.setAge( 29 );
Person[] persons = new Person[] { person1, person2, person3 };
ComparatorChain comparatorChain = new ComparatorChain( );
comparatorChain.addComparator( new BeanComparator( "lastName" ) );
comparatorChain.addComparator( new BeanComparator( "firstName" ) );
comparatorChain.addComparator( new BeanComparator( "age" ), true );
Arrays.sort( persons, comparatorChain );This example sorts an array of Person objects: by lastName ascending, firstName ascending, and age descending. The sorted persons array will be in the following order:
the older James Payne, the younger James Payne, followed by Susan Payne.
The ChainedComparator successfully
sorts two objects with the same first and last names—falling back to the
age to provide the correct sort order.
A ComparatorChain evaluates
every Comparator in the chain as
needed. If the current Comparator
returns a zero, the next Comparator
is invoked until there are no more Comparator objects left in the chain. If the
final Comparator returns a zero
value, the ComparatorChain returns a
zero. The ComparatorChain implements
the Comparator interface and is an
aggregate of other Comparator
objects; it can be used wherever a Comparator is used, including array sorting
and as a Comparator for a tree-based
Collection implementation.
The ReverseComparator
(introduced in Recipe
4.3) makes more sense in light of the ComparatorChain. If you need to sort a
collection of objects for display, you might want to reverse a
particular Comparator in a ComparatorChain. In the previous example,
there are two people named "James Payne": one is 21 and the other is 85.
Your application respects age and you want to put the older James Payne
in front of the younger James Payne in the sorted list. Sorting by
lastName ascending, firstName ascending, and age descending calls for the last Comparator in the chain to be reversed; the
following code calls addComparator( )
with a second parameter, true,
causing the BeanComparator for
age to be reversed with ReverseComparator:
comparatorChain.addComparator( new BeanComparator( "age" ), true );
The previous statement is equivalent to the following code:
comparaterChain.addComparator( new ReverseComparator
(new BeanComparator("age") );Using a ComparatorChain may
remind you of the way a result set is sorted in a SQL SELECT statement. This recipe's Solution
implements the following SQL statement in a ComparatorChain:
SELECT * FROM person ORDER BY lastName ASC, firstName ASC, age DESC;
The BeanComparator was
introduced in the previous chapter; for more information, see Recipe 3.10. The ReverseComparator was introduced in Recipe 4.3.
