分享

EqualsBuilder和HashCodeBuilder

 posondlq 2011-08-02
自动化hashCode()和equals()   问题产生:当需要自动实现hashCode()和equals()方法   解决方法:使用EqualsBuilder和HashCodeBuilder   使用举例:  
import  org.apache.commons.lang.builder.HashCodeBuilder;
import
 org.apache.commons.lang.builder.EqualsBuilder;
 
public   class  PoliticalCandidate 
{
    
//
 Member variables - omitted for brevity
    
//
 Constructors - omitted for brevity
    
//
 get/set methods - omitted for brevity
    
//  A hashCode which creates a hash from the two unique identifiers

 
public   int  hashCode( ) 
         
 return   new  HashCodeBuilder( 17 37
) .append(firstName)
                        .append(lastName).toHashCode( );     }
   
 
//  An equals which compares two unique identifiers                 
         public   boolean  equals(Object o) 
{         
 
             boolean  equals  =   false ;         
 
            if  ( o  !=   null   && PoliticalCandidate. class .isAssignableFrom(o) )  {
             PoliticalCandidate pc 
=
 (PoliticalCandidate) o;             
               equals 
=  ( new
 EqualsBuilder( ) .append(firstName, ps.firstName)   
                                  .append(lastName, ps.lastName)).isEquals( );        
              }
        
   
             return  equals;     
       }

}
Discussion: 1.在上述例子中,当有相同的firstname和lastname时,认为两个对象的hashCode相同,从而equals()返回true. 如果hashCode取决于该class的所有filed时需要使用反射机制来产生一个hashCode。
public   int  hashCode( )  {      return  HashCodeBuilder.reflectionHashCode( this ); }
和ToStringBuilder 与 HashCodeBuilder一样EqualsBuilder 也是使用append()方法进行配置, EqualsBuilder的append()方法可以接受基本类型、对象、数组作为参数。EqualsBuilder强大的地方在于可以直接把数组作为参数传入append()方法,EqualsBuilder会依次比较数组中的每个元素。 2.如果两个对象相等当且仅当每个属性值都相等 这句话可以由以下代码实现:
public   boolean  equals(Object o)  {      return  EqualsBuilder.reflectionEquals( this , o); }

问题提出:需要快速实现compareTo()方法解决方法:使用CompareToBuilder提供的compareTo()方法。同样的CompareToBuilder也使用了反射机制。以下代码提供了一个compareTo()方法,用于比较两个对象所有的非static和非transient成员变量。

import  org.apache.commons.lang.builder.CompareToBuilder; //  Build a compareTo function from reflection  public   int  compareTo(Object o)  {      return  CompareToBuilder.reflectionCompare( this , obj); }
Discussion: CompareToBuilder.reflectionCompare ()提供了两个对象non-static和nontransient成员变量的方法。 reflectionCompare()方法不予理会static和transient变量,因此以下代码中的averageAge和fullName变量是不会进入比较表达式的。
public   class  PoliticalCandidate  {     
                //  Static variable
    
 
                private   static  String averageAge;     
               //  Member variables 
    
 
               private  String firstName;     
               private
 String lastName;     
               private   transient
 String fullName;     
              //
 Constructors     
 
             //  get/set methods     
 
            //  Build a compareTo function from reflection 
     
              public   int  compareTo(Object o) 
{         
                  return  CompareToBuilder.reflectionCompare( this
, obj);    
              }

 }
比较对象成员变量的时候应该有一个比较的次序存在,上述代码中默认的应该是先比较lastName,然后是firstName。调用append()方法可以把要比较的变量加入比较表达式中,并且遵循后加入的先比较的次序。例如:
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;
         }
在比较的时候会先比较lastName,只有在lastName相同的情况下才会比较firstName。 ps:实现compareTo()的时候应保证和equals()规则相同,即当compareTo()返回是0的时候equals()应该返回true。

1.1 ReflectionToStringBuilder

本笔记是在阅读Jakarta Commons Cookbook时所留下的。 1.使用ReflectionToStringBuilder 或者ToStringBuilder 自动产生toString()的内容。    使用举例:假设有一个表征校长候选人信息的javabean-PoliticalCandidate。   
public class PoliticalCandidate {     
 
             private String lastName;    
             
private String firstName;    
             
private Date dateOfBirth;    
            
private BigDecimal moneyRaised;     
 
             private State homeState;     
 
             // get/set方法省略   
      
public void toString( ) {
         ReflectionToStringBuilder.toString( 
this );     
       }
 
}
该bean里面有个toString()方法,假设有以下操作:
// Create a State
 
   State va = new State( "VA""Virginia");
 
   // Create a Birth Date
 
   Calendar calendar = new GregorianCalendar( );
   calendar.set( Calendar.YEAR, 
1743 );
   calendar.set( Calendar.MONTH, Calendar.APRIL );
   calendar.set( Calendar.DAY_OF_MONTH, 
13 );
   Date dob 
= calendar.getTime( );
   BigDecimal moneyRaised 
= new BigDecimal( 293829292.93 );        
 
// Create a Political Candidate
 
   PoliticalCandidate candidate =      new PoliticalCandidate( "Jefferson""Thomas", dob, moneyRaised, va );      
   System.out.println( candidate );
假设State对象也是一个使用ReflectionToStringBuilder的javabean,
上述程序一种可能的输出为
com.discursive.jccook.lang.builders.PoliticalCandidate@187aeca    
[lastName=Jefferson,\firstName=Thomas,dateOfBirth=Sat Apr 13 22:38:42 CST 1743,moneyRaised=\293829292.930000007152557373046875,      state=\com.discursive.jccook.lang.builders.State@87816d  [abbreviation=VA,name=Virginia]]

 

org.apache.commons.lang.builder   
CompareToBuilder – 用于辅助实现Comparable.compareTo(Object)方法;    
EqualsBuilder – 用于辅助实现Object.equals()方法;    
HashCodeBuilder – 用于辅助实现Object.hashCode()方法;    
ToStringBuilder – 用于辅助实现Object.toString()方法;    
ReflectionToStringBuilder – 使用反射机制辅助实现Object.toString()方法;    
ToStringStyle – 辅助ToStringBuilder控制输出格式;    
StandardToStringStyle – 辅助ToStringBuilder控制标准格式。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多