Apache Commons 等于/哈希代码构建器 [英] Apache Commons equals/hashCode builder

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

问题描述

我很想知道这里的人们对使用org.apache.commons.lang.builder EqualsBuilder/HashCodeBuilder用于实现 equals/hashCode?这会比自己编写更好的做法吗?它与 Hibernate 兼容吗?你有什么看法?

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?

推荐答案

commons/lang 构建器很棒,我已经使用它们多年了,没有明显的性能开销(有和没有休眠).但正如 Alain 所写,Guava 方式甚至更好:

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:

这是一个示例 Bean:

Here's a sample Bean:

public class Bean{

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

}

这是使用 Commons/Lang 实现的 equals() 和 hashCode():

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;
    }
}

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

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;
    }
}

注意:此代码最初引用了 Guava,但正如评论所指出的,此功能已在 JDK 中引入,因此不再需要 Guava.

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.

如您所见,Guava/JDK 版本更短,并且避免了多余的辅助对象.在 equals 的情况下,如果较早的 Object.equals() 调用返回 false(公平地说:commons/lang 有一个 ObjectUtils.equals(obj1, obj2) 方法具有相同的语义,可以用来代替 EqualsBuilder 以允许如上所述的短路).

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).

所以:是的,commons lang 构建器比手动构建的 equals()hashCode() 方法(或者 Eclipse 会为你生成的那些可怕的怪物)更可取,但 Java 7+/Guava 版本甚至更好.

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.

关于 Hibernate 的说明:

And a note about Hibernate:

在你的 equals()、hashCode() 和 toString() 实现中使用惰性集合时要小心.如果您没有打开的 Session,那将会失败.

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.

注意(关于equals()):

Note (about equals()):

a) 在上面的 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) 根据您对 equals() 合同的解释,您还可以更改行

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

    if(obj instanceof Bean){

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

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

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:

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

(虽然是关于hashCode(),但同样适用于equals())

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

注意(灵感来自 kayahr 的评论)

Note (inspired by Comment from kayahr)

Objects.hashCode(..)(就像底层的 Arrays.hashCode(...))可能会表现不佳.在这种情况下,EqualsBuilder 实际上可能是更好的解决方案.

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 等于/哈希代码构建器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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