Common Java Cookbook

Edition: 0.19

Download PDF or Read on Scribd

Download Examples (ZIP)

1.7. Automating compareTo( )

1.7.1. Problem

You need a quick way to implement compareTo( ) methods.

1.7.2. Solution

Commons Lang CompareToBuilder provides a builder for compareTo( ) methods. CompareToBuilder can perform a comparison via reflection, or a comparison can be customized by passing parameters to an instance of CompareToBuilder. The following example demonstrates the use of the reflection builder to implement a compareTo( ) method. This implementation compares all nonstatic and nontransient member variables in both classes.

import org.apache.commons.lang.builder.CompareToBuilder;
// Build a compareTo function from reflection 
public int compareTo(Object o) {
    return CompareToBuilder.reflectionCompare(this, obj);
}

1.7.3. Discussion

CompareToBuilder.reflectionCompare( ) takes two objects and compares the non-static, nontransient member variables of these objects. In Example 1-2, the comparison involves the name properties of two PoliticalCandidate objects from Example 1-3, which are considered equal if both firstName and lastName are equal. reflectionCompare( ) ignores static fields and transients; therefore, in Example 1-3, averageAge and fullName do not contribute to the automated comparison.

Example 1-3. Implementing compareTo( ) using a reflection builder

public class PoliticalCandidate implements Comparable {
  private String lastName;
  private String firstName;
  private transient String fullName;
  
  // Static Variable
  private static String averageAge;
  
  
    // Constructors
    // get/set methods
    
    // Build a compareTo function from reflection 
    public int compareTo(Object o) {
        return CompareToBuilder.reflectionCompare(this, o);
    }    
  
}

In addition to a comparison by reflection, the CompareToBuilder can be configured to compare two objects by a set of variables in a particular order. The order of comparisons plays a key role when a comparison involves multiple member variables; this order is not specified when using the reflectionCompare() method. Assume that the default sorting behavior for PoliticalCandidate objects should be lastName and then firstName; if two objects have the same lastName, then sort by the firstName. The following example demonstrates a customization of the compareTo( ) method.

Calling append( ) specifies what variables will be compared and in what order they will be compared. The order of the calls to append( ) are backward—similar to pushing an object onto the top of a stack. The last property "pushed" onto the CompareToBuilder is the first property to be compared. Objects are compared by last name, and first name is used as a "tiebreaker." Example 1-4 will compare two PoliticalCandidate objects by lastName, falling back to firstName only if the lastName values were equal.

Example 1-4. Customizing a compareTo( ) method with CompareToBuilder

// A compare to that mimics the behavior of equals( )
public int compareTo(Object o) {
    int compare = -1; // By default return less-than
    if( o != null && 
        PoliticalCandidate.class.isAssignableFrom( o.getClass( ) ) ) {
            PoliticalCandidate pc = (PoliticalCandidate) o;
            compare = (new CompareToBuilder( )
                          .append(firstName, pc.firstName)
                          .append(lastName, pc.lastName)).toComparison( );
    }
    return compare;
}

Remember to keep the behavior of equals( ) and compareTo( ) consistent to avoid problems when sorting collections. Automating the compareTo( ) method via reflection may not compare objects in a way that is consistent with equals( ).

1.7.4. See Also

compareTo( ) methods provide the natural sorting order for a set of objects, and they are frequently used when sorting a collection of JavaBeans©. If you are trying to sort a collection of beans, you are better off using the BeanComparator, which is described in Recipe 3.10.

Instead of capturing comparison logic in a compareTo() method, consider using a Comparator object. The Commons Collections project contains a number of supplements to the Comparator interface, such as utilities to reverse and chain comparators. Comparator utilities are discussed in Chapter 4.


Creative Commons License
Common Java Cookbook by Tim O'Brien is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.
Permissions beyond the scope of this license may be available at http://www.discursive.com/books/cjcook/reference/jakartackbk-PREFACE-1.html. Copyright 2009. Common Java Cookbook Chunked HTML Output. Some Rights Reserved.