繁体   English   中英

我需要实现hashCode()和equals()方法吗?

[英]Do I need to implement hashCode() and equals() methods?

如果我有一个地图和一个对象作为地图键,是默认的哈希和等于方法吗?

class EventInfo{

    private String name;
    private Map<String, Integer> info
 }

然后我想创建一个地图:

Map<EventInfo, String> map = new HashMap<EventInfo, String>();

我是否必须显式实现hashCode()和equals()? 谢谢。

是的你是。 HashMap通过计算密钥的哈希码并将其用作基点来工作。 如果hashCode函数没有被覆盖(由你),那么它将使用内存地址, equals将与==相同。

如果您在Eclipse中,它将为您生成它们。 单击Source菜单→ Generate hashCode()和equals()

如果您没有Eclipse,那么这里应该有一些。 (我在Eclipse中生成了这些,如上所述。)

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((info == null) ? 0 : info.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (!(obj instanceof EventInfo)) {
        return false;
    }
    EventInfo other = (EventInfo) obj;
    if (info == null) {
        if (other.info != null) {
            return false;
        }
    } else if (!info.equals(other.info)) {
        return false;
    }
    if (name == null) {
        if (other.name != null) {
            return false;
        }
    } else if (!name.equals(other.name)) {
        return false;
    }
    return true;
}

是的,你需要它们,否则你将无法比较两个EventInfo(你的地图将不起作用)。

严格来说,没有。 hashCode()和equals()的默认实现将产生应该起作用的结果。 请参阅http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()

我的理解是hashCode()的默认实现通过在内存中获取对象的地址并转换为整数来工作,并且只有当两个对象实际上是同一个对象时,equals()的默认实现才返回true。

在实践中,您可以(而且应该)改进这两种实现。 例如,两种方法都应该忽略不重要的对象成员。 此外,equals()可能希望以递归方式比较对象中的引用。

在您的特定情况下,如果两个对象引用相同的字符串或两个字符串相等两个映射相同或相等则可以将equals()定义为true。 我认为WChargin给你很好的实现。

取决于你想要发生什么。 如果具有相同nameinfo两个不同的EventInfo实例应该导致两个不同的键,那么您不需要实现equalshashCode

所以

EventInfo info1 = new EventInfo();
info1.setName("myname");
info1.setInfo(null);
EventInfo info2 = new EventInfo();
info2.setName("myname");
info2.setInfo(null);

info1.equals(info2)将返回false和info1.hashCode()将不同的值返回info2.hashCode()

因此,当您将它们添加到地图时:

map.put(info1, "test1");
map.put(info2, "test2");

你会有两个不同的条目。

现在,这可能是期望的行为。 例如,如果您的EventInfo正在收集不同的事件,那么具有相同数据的两个不同事件可能希望成为两个不同的条目。

equalshashCode合约也适用于Set

例如,如果您的活动信息包含鼠标点击,那么您可能希望最终得到:

Set<EventInfo> collectedEvents = new HashSet<EventInfo>();
collectedEvents.add(info1);
collectedEvents.add(info2);

2个收集的活动,而不仅仅是1 ...

希望我在这里有意义......

编辑:

但是,如果上面的set和map应该只包含一个条目,那么你可以使用apache commons EqualsBuilderHashCodeBuilder来简化equalshashCode的实现:

@Override
public boolean equals(Object obj) {
    if (obj instanceof EventInfo) {
        EventInfo other = (EventInfo) obj;
        EqualsBuilder builder = new EqualsBuilder();
        builder.append(name, other.name);
        builder.append(info, other.info);
        return builder.isEquals();
    }
    return false;
}

@Override
public int hashCode() {
    HashCodeBuilder builder = new HashCodeBuilder();
    builder.append(name);
    builder.append(info);
    return builder.toHashCode();
}

EDIT2:

如果两个EventInfo实例具有相同的名称,也可能是合适的,例如,如果name是某个唯一标识符(我知道它与您的特定对象有点牵强,但我在这里进行了概括)。 ..)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM