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.