`
lionheartyd
  • 浏览: 4790 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

EqualsBuilder和HashCodeBuilder 自动化hashCode()和equals()

    博客分类:
  • java
 
阅读更多
问题产生:当需要自动实现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控制标准格式。
------------------------------------------------------------------
Apache Commons Lang之hashCode()、equals()和compareTo()

Apache Commons Lang提供一套生成hashCode()、equals()和compareTo()的API,简单易用。这个与toString()工具用法类似。

一、实现策略

1、hashCode()
通过HashCodeBuilder反射来生成,这说明类的hashCode与类中所有的域都相关。
也可以通过HashCodeBuilder实例来制定生成。

2、equals()
也有两种生成方式,与toString()、hashCode()的生成策略类似。

3、compareTo()
与以上都类似。

二、实例

为了测试,创佳两个类 Foo、Bar,参看上篇文章,分别通过两种方式实现其hashCode()和equals()方法

public class Foo {
        private String name;
        private int age;
        private Bar bar;

        public Foo(String name, int age) {
                this.name = name;
                this.age = age;
        }

        //省略getter/setter方法

}

public class Bar {
        private String name;

        public Bar(String name) {
                this.name = name;
        }

        //省略getter/setter方法

}

1、实现hashCode()

反射方式
        @Override
        public int hashCode() {
                return HashCodeBuilder.reflectionHashCode(this);

        }

制定方式
        @Override
        public int hashCode() {
                return new HashCodeBuilder(17, 37)
                                .append(name)
                                .append(age)
                                .append(bar)
                                .toHashCode();
        }

2、实现equals()

反射方式
        @Override
        public boolean equals(Object obj) {
                return EqualsBuilder.reflectionEquals(this, obj);
        }

制定方式

        @Override
        public boolean equals(Object obj) {
                boolean flag = false;
                if (obj != null && Foo.class.isAssignableFrom(obj.getClass())) {
                        Foo f = (Foo) obj;
                        flag = new EqualsBuilder()
                                        .append(name, f.getName())
                                        .append(age, f.getAge())
                                        .append(bar, f.getBar()).isEquals();
                }
                return flag;
        }

3、生成compareTo()
当然,实现compareTo()的前提是Foo类实现了Comparable接口。否则没啥意义。

反射实现
        public int compareTo(Object obj) {
                return CompareToBuilder.reflectionCompare(this, obj);

        }

制定实现
        public int compareTo(Object obj) {
                int flag = -1;
                if (obj != null && Foo.class.isAssignableFrom(obj.getClass())) {
                        Foo f = (Foo) obj;
                        flag = new CompareToBuilder()
                                        .append(name, getName())
                                        .append(age, f.getAge())
                                        .append(bar, f.getBar())
                                        .toComparison();
                }
                return flag;
        }
分享到:
评论

相关推荐

    1_equals_overridingequals_

    在实践中,为了代码的可读性和一致性,可以考虑使用Apache Commons Lang库的EqualsBuilder和HashCodeBuilder,或者使用Lombok库的@EqualsAndHashCode注解,它们可以帮助我们更方便地生成这些方法。 总的来说,重写...

    commons-lang

    6. EqualsBuilder/HashCodeBuilder提供了方便的方法来覆盖equals() 和hashCode()方法 7.以Range结尾的类主要提供一些范围的操作,包括判断某些字符,数字等是否在这个范围以内 8.ArrayUtils 提供了数组的复制,查找,...

    eclipse插件 org.jiayun.commons4e

    4. 配置友好:org.jiayun.commons4e插件提供了丰富的配置选项,允许用户根据项目需求定制生成的代码格式,如是否忽略特定字段,是否使用Apache Commons Lang的EqualsBuilder和HashCodeBuilder等。 安装此插件,用户...

    实用小工具:Java实体类对比、Json对比、字符串动态拼接等功能

    对比两个实体类,可能涉及到对象的属性比较,例如使用Apache的EqualsBuilder和HashCodeBuilder来实现对象的equals()和hashCode()方法,以确保对象内容一致时返回相同的结果。此外,还可以使用Lombok库的@...

    commons-lang3-3.3.2

    例如,`HashCodeBuilder`和`EqualsBuilder`可以确保在添加或删除字段时,`equals()`和`hashCode()`的实现不会忘记更新。`ToStringBuilder`则可以帮助生成整洁、易读的调试信息,这对于理解复杂对象的状态非常有用。 ...

    JAVA中实现“相等”比较的深入分析.zip

    实现`equals()`和`hashCode()`的一个常见模式是使用Apache Commons Lang库的`EqualsBuilder`和`HashCodeBuilder`,它们可以简化代码并减少错误的可能性。 此外,还要注意`equals()`和`compareTo()`的区别。`...

    复杂对象的比较

    Java社区提供了一些工具类和库来简化对象比较,例如Apache Commons Lang的`EqualsBuilder`和`HashCodeBuilder`,或者Google的Guava库中的`Objects.equal()`和`Objects.hashCode()`。 在实际编程中,确保复杂对象的...

    Jakarta Commons CookBook学习笔记

    `EqualsBuilder` 和 `HashCodeBuilder` 是 Apache Commons Lang 包中提供的两个工具类,用于简化 `equals()` 和 `hashCode()` 方法的实现。这些方法对于 Java 对象来说非常重要,尤其是在将对象放入集合(如 HashSet...

    allequals:Java equalshashCode 基准代码

    测试可能包括不同策略的比较,比如简单的属性比较、深比较、以及使用工具类如Apache Commons Lang的EqualsBuilder和HashCodeBuilder。 总结来说,`equals()` 和 `hashCode()` 在Java中是核心的比较和哈希机制,正确...

    apache-commons-lang.zip 源码

    此外,`EqualsBuilder`和`HashCodeBuilder`是构建自定义equals()和hashCode()方法的强大工具,它们遵循了Java equals()和hashCode()的一致性原则。`ToStringBuilder`则帮助创建对象的toString()方法输出,使得调试和...

    java list 比较详解及实例

    在 Commons-Collections4 中增加了外部输入 equals 和 hashCode 的方法,甚至 equals 和 hashCode 方法本身也不需要我们自己写代码,可以用 Commons-Lang 包实现。 三、使用 Apache Commons 实现 List 比较 使用 ...

    Hibernate中对数据库复合主键的支持.pdf

    这里使用了`Objects.equals()`和`Objects.hash()`方法来简化`equals`和`hashCode`方法的编写。另外,也可以通过引入Apache Commons Lang库中的`EqualsBuilder`和`HashCodeBuilder`来进一步简化代码: ```java ...

    看例子练apache_commons之lang篇

    `SerializationUtils` 类提供了一种简便的方式来序列化和反序列化对象。 - **SerializationUtils.serialize()**: 序列化对象。 - **SerializationUtils.deserialize()**: 反序列化对象。 #### 八、...

    commons-lang3-3.5-bin.zip

    `EqualsBuilder` 和 `HashCodeBuilder` 则帮助实现自定义的 equals() 和 hashCode() 方法。 7. **异常处理**:`ExceptionUtils` 提供了处理和包装异常的功能,简化异常处理代码。 8. **其他工具类**:`ArrayUtils`...

    48-Java知识点 手写HashMap1

    Apache Commons Lang库中的HashCodeBuilder和EqualsBuilder可以帮助开发者更方便地实现这些方法。 此外,HashMap还有一个内部字段`modCount`,在ArrayList和HashMap中都有,用于记录结构修改的次数,主要用于并发...

    commons-lang3-3.3.1.rar

    7. **对象工具**:`EqualsBuilder` 和 `HashCodeBuilder` 用于构建自定义的equals()和hashCode()方法,确保对象比较的正确性。 8. **枚举工具**:`EnumUtils` 提供了对Java枚举类型的增强操作,如遍历枚举值、验证...

    apache commons-lang简介

    这个包主要是为了提供对象构建和比较的工具,如ToStringBuilder、HashCodeBuilder和EqualsBuilder,它们帮助开发者生成对象的toString、hashCode和equals方法,避免了重复的样板代码。 以上只是Commons Lang的一...

    commons-lang3-3.10.rar

    10. **Object utilities**:`Objects`类提供了通用的对象操作,例如`EqualsBuilder`和`HashCodeBuilder`用于构建更安全的equals()和hashCode()方法。 11. **Functional programming**:`Function`、`Predicate`和`...

    commons-lang3-3.1-src.zip

    `EqualsBuilder`和`HashCodeBuilder`简化了自定义对象的`equals()`和`hashCode()`方法的实现。 9. **类型转换**:`TypeConverter`接口和`TypeConversionUtils`类支持在不同数据类型间的转换,增强了类型安全。 10....

    commons-lang3-3.7

    8. **对象创建和比较**:`ObjectUtils`和`EqualsBuilder`、`HashCodeBuilder`类提供了对象的创建、比较和深浅拷贝功能,有助于实现自定义的equals()和hashCode()方法。 9. **随机数生成**:`RandomUtils`类提供了...

Global site tag (gtag.js) - Google Analytics