下面是正确的equals和hashCode在Java中的实现吗?
当一个对象的值相等时,我需要返回它为真 范例下面是正确的equals和hashCode在Java中的实现吗?,java,hashcode,Java,Hashcode,当一个对象的值相等时,我需要返回它为真 范例 @Override public int hashCode() { return new HashCodeBuilder().append(value).toHashCode(); } @Override public boolean equals(final Object obj) { if (obj instanceof NumberValTO) { final NumberValTO other = (NumberVal) obj;
@Override
public int hashCode() {
return new HashCodeBuilder().append(value).toHashCode();
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof NumberValTO) {
final NumberValTO other = (NumberVal) obj;
return new EqualsBuilder().append(value, other.getValue()).isEquals();
}
return false;
}
以上是正确的还是错误的
我在一些应用程序中看到哈希代码在表的每个字段都是多个的,并且不确定这是否是一种正确的方法
假设一个实体有4列
假设一个实体有两列
谢谢。您的示例很好,因为它提供了equals和hashcode方法的公平实现。我在我的项目中使用这种方式 要回答你1个问题,你可以通读
要回答您的2个问题,请点击链接:是的,这很好,假设您正在使用的是Apache Commons helper类@Vino指出添加
if(obj==this)返回true是正确的在equals
方法的开头,code>是一个值得优化的方法,但是您的方法看起来是正确的。您的equals
和hashCode
方法都正确地使用了Apache的和,尽管您应该添加一个参考检查-if(obj==此)将true
-返回到equals
方法
我最近反对使用的一个论点是,它的性能较差,所以我对它进行了测试
我创建了一个HashMap
,添加了10K个条目,然后比较了同一个键对象的查找时间,一次使用传统的equals
和hashCode
,然后再次使用and。其思想是,通过键获取值将敲打equals
和hashCode
方法,并对它们的性能进行很好的比较
虽然实现速度较慢,但差异在60纳秒的范围内,实现的平均查找时间约为320纳秒,传统方法的平均查找时间约为260纳秒(我在下面展示了我使用的代码)
IMHO只有在大量对象上重复调用equals
和hashCode
时,才应该考虑这种性能损失,即使如此,也只有在牺牲代码清晰度的情况下,才值得牺牲较小的性能增益
不管怎样,下面是我用来测试性能差异的类:
public class Example
{
private Type operationType;
private long identity;
private String name;
private BigDecimal value;
public Example(Type operationType, long identity, String name, BigDecimal value)
{
this.operationType = operationType;
this.identity = identity;
this.name = name;
this.value = value;
}
public Example(Example example)
{
this.operationType = example.operationType;
this.identity = example.identity;
this.name = example.name;
this.value = example.value;
}
public long getIdentity()
{
return identity;
}
public String getName()
{
return name;
}
public BigDecimal getValue()
{
return value;
}
@Override
public boolean equals(Object obj)
{
if (Type.TRADITIONAL.equals(operationType))
{
if (this == obj)
{
return true;
}
if (obj == null || getClass() != obj.getClass())
{
return false;
}
Example example = (Example)obj;
return getIdentity() == example.getIdentity()
&& ((getName() == null && example.getName() == null) || getName().equals(example.getName ()))
&& ((getValue() == null && example.getValue() == null) || getValue().equals(example.getValue()));
}
else
{
return this == obj || obj instanceof Example &&
new EqualsBuilder()
.append(getIdentity(), ((Example)obj).getIdentity())
.append(getName(), ((Example)obj).getName())
.append(getValue(), ((Example)obj).getValue())
.isEquals();
}
}
@Override
public int hashCode()
{
if (Type.TRADITIONAL.equals(operationType))
{
int result = (int)(getIdentity() ^ (getIdentity() >>> 32));
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
return result;
}
else
{
return new HashCodeBuilder().append(getIdentity()).append(getName()).append(getValue()).toHashCode();
}
}
public static enum Type
{
TRADITIONAL,
COMMONS
}
}
下面是测试:
public class ExampleTest
{
@Test
public void testMapLookupWithTraditional() throws Exception
{
double total = 0;
for (int i = 0; i < 10; i++)
{
total += testMapLookup(Example.Type.TRADITIONAL);
}
System.out.println("Overall Average: " + (total / 10));
}
@Test
public void testMapLookupWithCommons() throws Exception
{
double total = 0;
for (int i = 0; i < 10; i++)
{
total += testMapLookup(Example.Type.COMMONS);
}
System.out.println("Overall Average: " + (total / 10));
}
private double testMapLookup(Example.Type operationType) throws Exception
{
Map<Example, String> examples = new HashMap<Example, String>();
while (examples.size() < 10000)
{
long now = System.currentTimeMillis();
Example example = new Example(
operationType,
now,
"EXAMPLE_" + now,
new BigDecimal(now)
);
examples.put(example, example.getName());
Thread.sleep(1);
}
int count = 0;
double average = 0;
double max = 0;
double min = Double.MAX_VALUE;
for (Example example : examples.keySet())
{
Example copiedExample = new Example(example);
long start = System.nanoTime();
examples.get(copiedExample);
long duration = System.nanoTime() - start;
average = ((average * count++) + duration) / count;
if (max < duration) max = duration;
if (min > duration) min = duration;
}
System.out.println("Average: " + average);
System.out.println("Max: " + max);
System.out.println("Min: " + min);
return average;
}
}
公共类示例测试
{
@试验
public void testMapLookupWithTraditional()引发异常
{
双倍合计=0;
对于(int i=0;i<10;i++)
{
total+=testMapLookup(Example.Type.TRADITIONAL);
}
系统输出打印项次(“总平均:+(总计/10));
}
@试验
public void testMapLookupWithCommons()引发异常
{
双倍合计=0;
对于(int i=0;i<10;i++)
{
total+=testMapLookup(Example.Type.COMMONS);
}
系统输出打印项次(“总平均:+(总计/10));
}
私有双testMapLookup(Example.Type operationType)引发异常
{
Map examples=newhashmap();
while(示例.size()<10000)
{
long now=System.currentTimeMillis();
示例=新示例(
操作类型,
现在
“示例”+现在,
新的BigDecimal(现在)
);
put(例如,example.getName());
睡眠(1);
}
整数计数=0;
双平均=0;
双最大值=0;
双最小值=双最大值;
例如(示例:examples.keySet())
{
示例copiedExample=新示例(示例);
长启动=System.nanoTime();
示例.get(复制示例);
长持续时间=System.nanoTime()-开始;
平均=((平均*计数++)+持续时间)/计数;
如果(最大值<持续时间)最大值=持续时间;
如果(分钟>持续时间)分钟=持续时间;
}
System.out.println(“平均值:+平均值”);
System.out.println(“Max:+Max”);
System.out.println(“Min:+Min”);
收益率平均值;
}
}
取决于HashCodeBuilder
&equalBuilder
的功能。里面可能有乘法(正确性不需要乘法-请参阅)。您的equals
方法还应该与null进行比较,并与self进行比较(this
)。例如,与相比,这是一个好主意,尽管它只是一个性能优化null
检查已经包括在内,因为null instanceof any
是false
。感谢链接。您是否发现上述hashcode或equals中存在任何问题??为什么我们需要编写自己的逻辑而不是使用上面的???@Vinoinstanceof
返回false表示null,与相比,这纯粹是性能优化。方法很好。非常感谢你的回答