EqualsBuilder和HashCodeBuilder(重写equal和hashcode)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EqualsBuilder和HashCodeBuilder(重写equal和hashcode)相关的知识,希望对你有一定的参考价值。

自动化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,上述程序一种可能的输出为[email protected]
    [lastName=Jefferson,\firstName=Thomas,
     dateOfBirth=Sat Apr 13 22:38:42 CST 1743,
     moneyRaised=\293829292.930000007152557373046875,
     state=\[email protected]
         [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控制标准格式。

自动化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,上述程序一种可能的输出为[email protected]
    [lastName=Jefferson,\firstName=Thomas,
     dateOfBirth=Sat Apr 13 22:38:42 CST 1743,
     moneyRaised=\293829292.930000007152557373046875,
     state=\[email protected]
         [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控制标准格式。

以上是关于EqualsBuilder和HashCodeBuilder(重写equal和hashcode)的主要内容,如果未能解决你的问题,请参考以下文章

ArrayUtils 方法

ToStringBuilder学习:常用方法介绍

Spring4 In Action-5.2.3-Spring Web应用程序-向页面输出列表接收参数接收表单

& 和 && 区别和联系,| 和 || 区别和联系

第三十一节:扫盲并发和并行同步和异步进程和线程阻塞和非阻塞响应和吞吐等

shell中$()和 ` `${}${!}${#}$[] 和$(()),[ ] 和(( ))和 [[ ]]