Apache Commons等于/ hashCode构建器 [英] Apache Commons equals/hashCode builder

查看:133
本文介绍了Apache Commons等于/ hashCode构建器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很想知道,人们在这里想到使用
org.apache.commons.lang.builder EqualsBuilder / HashCodeBuilder
用于实现等于 / hashCode ?这会比写自己的做法更好吗?它与Hibernate一起玩的很好吗?您的意见是什么?

解决方案

Commons / lang构建器非常好,我一直在使用它们多年,没有明显的性能开销并没有休眠)。但正如Alain所写,Guava的方式更好:

下面是一个示例Bean:

  public class Bean {

private String name;
private int length;
私人列表< Bean>儿童;




这些是用Commons / Lang:

  @Override 
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();

$ b @Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other =(Bean) OBJ;
返回新的EqualsBuilder()
.append(name,other.name)
.append(length,other.length)
.append(children,other.children)
.isEquals();
} else {
return false;


$ / code $ / pre

这里用Java 7或更高版本(受Guava ):

  @Override 
public int hashCode(){
返回Objects.hash(name,length ,儿童);

$ b @Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other =(Bean) OBJ;
返回Objects.equals(name,other.name)
&& length == other.length //针对原语的特殊处理
&& Objects.equals(children,other.children);
} else {
return false;






注意:此代码最初引用了Guava,但是作为注释已经指出,这个功能已经在JDK中引入了,因此不再需要Guava。


正如您所看到的,Guava / JDK版本更短并且避免了多余的辅助对象。在等于的情况下,如果以前的 Object.equals()调用返回false(公平:commons / lang的值为<$具有相同语义的c $ c> ObjectUtils.equals(obj1,obj2)方法可以用来代替 EqualsBuilder 允许如上所述的短路)


$ b 所以:是的,公用lang构建器比手动构建的 equals() hashCode()方法(或者Eclipse为您生成的那些可怕的怪物),但Java 7+ / Guava版本甚至更好。



关于Hibernate的一个注意:



在equals(),hashCode()和toString()实现中使用懒惰集合时要小心。如果您没有公开会话,这将会失败。




注意(关于equals()):在上面的两个版本的equals()中,你可能想要使用这两个快捷键中的一个或两个:



$ b pre> @Override
public boolean equals(final Object obj){
if(obj == this)return true; //测试引用是否相等
if(obj == null)return false; //测试为空
//如上继续



取决于您的解释如果(obj instanceof Bean){
())等于()合约,您可能也会更改这行($)

   

  //确保你在这个
之前运行一个空的检查if(obj.getClass()== getClass()){

如果您使用第二个版本,您可能还希望在 equals()中调用 super(equals())方法。意见不同,这个问题讨论这个话题:


将超类整合到Guava Objects.hashcode()实现中的正确方法?

hashCode(),同样适用于 equals()




注意(来自 kayahr 的评论)

Objects.hashCode(..)(就像底层的 Arrays .hashCode(...))可能执行得很糟糕,如果你有很多原始字段。在这种情况下, EqualsBuilder 实际上可能是更好的解决方案。


I'm curious to know, what people here think about using org.apache.commons.lang.builder EqualsBuilder/HashCodeBuilder for implementing the equals/hashCode? Would it be a better practice than writing your own? Does it play well with Hibernate? What's your opinion?

解决方案

The commons/lang builders are great and I have been using them for years without noticeable performance overhead (with and without hibernate). But as Alain writes, the Guava way is even nicer:

Here's a sample Bean:

public class Bean{

    private String name;
    private int length;
    private List<Bean> children;

}

Here's equals() and hashCode() implemented with Commons/Lang:

@Override
public int hashCode(){
    return new HashCodeBuilder()
        .append(name)
        .append(length)
        .append(children)
        .toHashCode();
}

@Override
public boolean equals(final Object obj){
    if(obj instanceof Bean){
        final Bean other = (Bean) obj;
        return new EqualsBuilder()
            .append(name, other.name)
            .append(length, other.length)
            .append(children, other.children)
            .isEquals();
    } else{
        return false;
    }
}

and here with Java 7 or higher (inspired by Guava):

@Override
public int hashCode(){
    return Objects.hash(name, length, children);
}

@Override
public boolean equals(final Object obj){
    if(obj instanceof Bean){
        final Bean other = (Bean) obj;
        return Objects.equals(name, other.name)
            && length == other.length // special handling for primitives
            && Objects.equals(children, other.children);
    } else{
        return false;
    }
}

Note: this code originally referenced Guava, but as comments have pointed out, this functionality has since been introduced in the JDK, so Guava is no longer required.

As you can see the Guava / JDK version is shorter and avoids superfluous helper objects. In case of equals, it even allows for short-circuiting the evaluation if an earlier Object.equals() call returns false (to be fair: commons / lang has an ObjectUtils.equals(obj1, obj2) method with identical semantics which could be used instead of EqualsBuilder to allow short-circuiting as above).

So: yes, the commons lang builders are very preferable over manually constructed equals() and hashCode() methods (or those awful monsters Eclipse will generate for you), but the Java 7+ / Guava versions are even better.

And a note about Hibernate:

be careful about using lazy collections in your equals(), hashCode() and toString() implementations. That will fail miserably if you don't have an open Session.


Note (about equals()):

a) in both versions of equals() above, you might want to use one or both of these shortcuts also:

@Override
public boolean equals(final Object obj){
    if(obj == this) return true;  // test for reference equality
    if(obj == null) return false; // test for null
    // continue as above

b) depending on your interpretation of the equals() contract, you might also change the line(s)

    if(obj instanceof Bean){

to

    // make sure you run a null check before this
    if(obj.getClass() == getClass()){ 

If you use the second version, you probably also want to call super(equals()) inside your equals() method. Opinions differ here, the topic is discussed in this question:

right way to incorporate superclass into a Guava Objects.hashcode() implementation?

(although it's about hashCode(), the same applies to equals())


Note (inspired by Comment from kayahr)

Objects.hashCode(..) (just as the underlying Arrays.hashCode(...)) might perform badly if you have many primitive fields. In such cases, EqualsBuilder may actually be the better solution.

这篇关于Apache Commons等于/ hashCode构建器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆