Apache Commons 等于/哈希代码构建器 [英] Apache Commons equals/hashCode builder
问题描述
我很想知道这里的人们对使用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屋!