Use
BeanComparator
to compare two beans using a bean property, which can be simple,
nested, indexed, or mapped. BeanComparator
obtains
the value of the same bean property from two objects and, by default,
compares the properties with a
ComparableComparator
. The following example sorts
a list of Country
objects using a
BeanComparator
and the default
ComparableComparator
:
import java.util.*; import org.apache.commons.beanutils.BeanComparator; Country country1 = new Country( ); country1.setName( "India" ); Country country2 = new Country( ); country2.setName( "Pakistan" ); Country country3 = new Country( ); country3.setName( "Afghanistan" ); // Create a List of Country objects Country[] countryArray = new Country[] { country1, country2, country3 }; List countryList = Arrays.asList( countryArray );// Sort countries by name
Comparator nameCompare = new BeanComparator( "name" );
Collections.sort( countryList, nameCompare );
System.out.println( "Sorted Countries:" ); Iterator countryIterator = countryList.iterator( ); while( countryIterator.hasNext( ) ) { Country country = (Country) countryIterator.next( ); System.out.println( " Country: " + country.getName( ) ); }
This code creates three Country
objects with
different names, places the Country
objects into a
list, and sorts this list with a BeanComparator
configured to compare by the bean property name
.
This code executes and prints the sorted list of countries:
Sorted Countries: Country: Afghanistan Country: India Country: Pakistan
The previous example demonstrated the default behavior of
BeanComparator
; when a
BeanComparator
is constructed with only one
parameter, it uses a ComparableComparator
to
compare the values of the properties it retrieves. You can also
construct a BeanComparator
with an instance of
Comparator
; in this case,
BeanComparator
decorates another
Comparator
, retrieving the values of a property
and passing these values on to an instance of
Comparator
. The following example demonstrates the
use of BeanComparator
with a custom
Comparator
implementation. This example involves
two objects shown in Figure 3-6:
ElectricVehicle
and Engine
.
An application needs to sort ElectricVehicle
objects by efficiency, and, in this contrived example, efficiency is
defined as the number of miles per gallon times the percentage of
electric operation; an 80% electric hybrid vehicle is more efficient
than a 25% electric hybrid vehicle with the same mileage because of
reduced emissions. The code fragments shown in Example 3-5 sort a collection of beans by wrapping a
custom Comparator
with a
BeanComparator
.
Example 3-5. Decorating a Comparator with a BeanComparator
import java.util.*; import org.apache.commons.beanutils.BeanComparator; // Create Engines Engine engine1 = new Engine( ); engine1.setMilesGallon( new Integer(60) ); engine1.setPercentElectric( new Integer(50) ); Engine engine2 = new Engine( ); engine2.setMilesGallon( new Integer(90) ); engine2.setPercentElectric( new Integer(50) ); Engine engine3 = new Engine( ); engine3.setMilesGallon( new Integer(65) ); engine3.setPercentElectric( new Integer(45) ); // Create Vehicles ElectricVehicle vehicle1 = new ElectricVehicle( ); vehicle1.setMake( "Toy Yoda" ); vehicle1.setModel( "Electro" ); vehicle1.setYear( 2005 ); vehicle1.setEngine( engine1 ); ElectricVehicle vehicle2 = new ElectricVehicle( ); vehicle2.setMake( "Fjord" ); vehicle2.setModel( "Photon" ); vehicle2.setYear( 2004 ); vehicle2.setEngine( engine2 ); ElectricVehicle vehicle3 = new ElectricVehicle( ); vehicle3.setMake( "Ford" ); vehicle3.setModel( "Electric Pinto" ); vehicle3.setYear( 2005 ); vehicle3.setEngine( engine3 ); // Create List of Vehicles List vehicles = new ArrayList( ); vehicle.add( vehicle1 ); vehicle.add( vehicle2 ); vehicle.add( vehicle3 ); // Define Engine Comparison Logic in an Anonymous inner class // which implements the Comparator interface Comparator engineCompare = new Comparator( ) { public int compare(Object o1, Object o2) { Engine engine1 = (Engine) o1; Engine engine2 = (Engine) o2; int engine1Temp = engine1.getMilesGallon( ).intValue( ) * engine1.getPercentElectric( ).intValue( ); int engine2Temp = engine2.getMilesGallon( ).intValue( ) * engine2.getPercentElectric( ).intValue( ); Integer engine1Factor = new Integer( engine1Temp ); Integer engine2Factor = new Integer( engine2Temp ); return engine1Factor.compareTo( engine2Factor ); } }Comparator vehicleCompare = new BeanComparator( "engine", engineCompare );
Collections.sort( vehicles, vehicleCompare );
// Print Sorted Results System.out.println( "Vehicles Sorted by Efficiency:" ); Iterator vehicleIter = vehicles.iterator( ); while( vehicleIter.hasNext( ) ) { ElectricVehicle vehicle = (ElectricVehicle) vehicleIter.next( ); System.out.println( " Vehicle: " + vehicle.getModel( ) + ", " + vehicle.getEngine( ).getMilesGallon( ) + " MPG, " + vehicle.getEngine( ).getPercentElectric( ) + "% Electric" ); }
engineCompare
contains the logic used to sort
vehicles by efficiency, and BeanComparator
supplies the engine
properties to this
Comparator
implementation. This previous example
creates three vehicles and sorts the vehicles in order of efficiency;
the following results are printed:
Vehicles Sorted by Efficiency: Vehicle: Photon, 90 MPG, 50% Electric Vehicle: Electro, 60 MPG, 50% Electric Vehicle: Electric Pinto, 65 MPG, 45% Electric
Chapter 4 provides examples of various
Comparator
implementations, which can be used to
decorate other comparators. One Comparator
in
particular is important if you plan to sort beans on a bean property,
which could be null
. If a bean property could be
null
, make sure to pass a
NullComparator
to
BeanComparator
; otherwise,
ComparableComparator
will throw a
NullPointerException
if a property value is
null
. Recipe 4.5
discusses techniques for decorating a Comparator
with NullComparator
.
Recipe 3.15 discusses a
BeanPredicate
object that can be used to validate beans. The
BeanPredicate
is similar to the
BeanComparator
as it decorates another instance of
Predicate
, providing access to a
bean property.
3.138.35.255