我们如何决定集合的hashCode()方法的最佳实现(假设equals方法已被正确重写)?
当前回答
下面是另一个考虑超类逻辑的JDK 1.7+方法演示。我认为它对对象类hashCode()进行记帐非常方便,纯粹依赖于JDK,没有额外的手工工作。请注意Objects.hash()是空容忍的。
我没有包括任何equals()实现,但实际上您当然需要它。
import java.util.Objects;
public class Demo {
public static class A {
private final String param1;
public A(final String param1) {
this.param1 = param1;
}
@Override
public int hashCode() {
return Objects.hash(
super.hashCode(),
this.param1);
}
}
public static class B extends A {
private final String param2;
private final String param3;
public B(
final String param1,
final String param2,
final String param3) {
super(param1);
this.param2 = param2;
this.param3 = param3;
}
@Override
public final int hashCode() {
return Objects.hash(
super.hashCode(),
this.param2,
this.param3);
}
}
public static void main(String [] args) {
A a = new A("A");
B b = new B("A", "B", "C");
System.out.println("A: " + a.hashCode());
System.out.println("B: " + b.hashCode());
}
}
其他回答
这里有一个非常严重的bug。
Zam obj1 = new Zam("foo", "bar", "baz");
Zam obj2 = new Zam("fo", "obar", "baz");
同样的hashcode
你可能想要
public int hashCode() {
return (getFoo().hashCode() + getBar().hashCode()).toString().hashCode();
(现在你能在Java中直接从int获取hashCode吗?我认为它做了一些自动铸造。如果是这种情况,跳过toString,它很难看。)
使用Apache Commons EqualsBuilder和HashCodeBuilder上的反射方法。
对于简单类,通常最容易基于equals()实现检查的类字段实现hashCode()。
public class Zam {
private String foo;
private String bar;
private String somethingElse;
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Zam otherObj = (Zam)obj;
if ((getFoo() == null && otherObj.getFoo() == null) || (getFoo() != null && getFoo().equals(otherObj.getFoo()))) {
if ((getBar() == null && otherObj. getBar() == null) || (getBar() != null && getBar().equals(otherObj. getBar()))) {
return true;
}
}
return false;
}
public int hashCode() {
return (getFoo() + getBar()).hashCode();
}
public String getFoo() {
return foo;
}
public String getBar() {
return bar;
}
}
最重要的是保持hashCode()和equals()的一致性:如果equals()对于两个对象返回true,那么hashCode()应该返回相同的值。如果equals()返回false,那么hashCode()应该返回不同的值。
如果你对dmeister推荐的Effective Java实现感到满意,你可以使用一个库调用来代替自己的调用:
@Override
public int hashCode() {
return Objects.hash(this.firstName, this.lastName);
}
这需要Guava (com.google.common.base.Objects.hashCode)或Java 7中的标准库(Java .util. objects .hash),但工作方式相同。
如果我正确理解你的问题,你有一个自定义的集合类(即一个从集合接口扩展的新类),你想实现hashCode()方法。
如果您的集合类扩展了AbstractList,那么您就不必担心它,因为已经有equals()和hashCode()的实现,它通过遍历所有对象并将它们的hashCodes()相加来工作。
public int hashCode() {
int hashCode = 1;
Iterator i = iterator();
while (i.hasNext()) {
Object obj = i.next();
hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
}
return hashCode;
}
现在,如果你想要的是计算特定类哈希码的最佳方法,我通常使用^(按位排他或)操作符来处理我在equals方法中使用的所有字段:
public int hashCode(){
return intMember ^ (stringField != null ? stringField.hashCode() : 0);
}
推荐文章
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- Maven依赖Servlet 3.0 API?
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表
- Spring JPA选择特定的列
- URLEncoder不能翻译空格字符
- Java中的super()
- 如何转换JSON字符串映射<字符串,字符串>与杰克逊JSON