【发布时间】:2015-09-18 17:10:43
【问题描述】:
我这样初始化 HashSet:
private HashSet<Rule> ruleTable = new HashSet<Rule>();
我的TcpRule 对象(抽象类Rule 的子类)的equals() 和hashCode() 方法如下所示:
@Override
public int hashCode() {
// Ignore source Port for now
return (this.getSrcPool() + ":" + this.getDstPool() + ":" + this.getProtocol() + ":" + this.dstTcp).hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TcpRule))
return false;
if (obj == this)
return true;
TcpRule r = (TcpRule) obj;
return (this.getSrcPool().equals(r.getSrcPool()) && this.getDstPool().equals(r.getDstPool()) && this.getProtocol().equals(r.getProtocol()) && this.getSrcTcp() == r.getSrcTcp() && this.getDstTcp() == r.getDstTcp());
}
我什至写了一个简单的单元测试,没有任何错误:
@Test
public void equalsTest() {
Pool srcPool = new Pool("PROXY");
Pool dstPool = new Pool("WEB");
int srcTcp = 54321;
int dstTcp = 80;
TcpRule r1 = new TcpRule(srcPool, dstPool, srcTcp, dstTcp);
TcpRule r2 = r1;
assert r1.equals(r2);
TcpRule r3 = new TcpRule(srcPool, dstPool, srcTcp, dstTcp);
TcpRule r4 = new TcpRule(srcPool, dstPool, srcTcp, dstTcp);
assert r3.equals(r4);
}
@Test
public void hashCodeTest() {
Pool srcPool = new Pool("PROXY");
Pool dstPool = new Pool("WEB");
int srcTcp = 54321;
int dstTcp = 80;
TcpRule r1 = new TcpRule(srcPool, dstPool, srcTcp, dstTcp);
TcpRule r2 = new TcpRule(srcPool, dstPool, srcTcp, dstTcp);
assert r1.hashCode() == r2.hashCode();
HashSet<Rule> rules = new HashSet<Rule>();
rules.add(r1);
assert rules.contains(r1);
assert rules.contains(r2);
}
在我的应用程序中,我有一个add() 方法,我只需将Rule 对象添加到HashSet:
@Override
public void add(Rule rule) {
ruleTable.add(rule);
}
在另一种方法中,我检查HashSet中是否存在规则:
@Override
public boolean isPermittedTcp(IpAddress sourceAddress, IpAddress destinationAddress, short srcTcp, short dstTcp) {
Pool sourcePool = poolService.getPool(new Host(sourceAddress));
Pool destinationPool = poolService.getPool(new Host(destinationAddress));
Rule r = new TcpRule(sourcePool, destinationPool, srcTcp, dstTcp);
log.info("Checking: " + r.toString());
log.info("Hash-Code: " + r.hashCode());
log.info("Hashes in ruleTable:");
for(Rule rT : ruleTable) {
log.info("" + rT.hashCode());
}
if(ruleTable.contains(r)) {
log.info("Hash found!");
} else {
log.info("Hash not found!");
}
return ruleTable.contains(r);
}
日志消息表明Rule 对象(r.hashCode())的哈希是-1313430269,而HashSet(循环中的rT.hashCode())中的一个哈希也是-1313430269。
但是ruleTable.contains(r) 总是返回false。我做错了什么?
我在 StackOverflow 上发现了类似的问题,但这些问题主要涉及 equals() 或 hashCode() 方法未被(正确)覆盖。我想我已经正确地实现了这两种方法。
【问题讨论】:
-
还有 rT.equals(r) 吗?
-
您的测试使用了相同的 Pool 实例,您确定 equals 在 Pool 上运行良好吗?
-
你在 equals this.getSrcTcp() == r.getSrcTcp() 中有一个额外的条件,它不是哈希码的一部分 - 也许这就是问题所在,哈希码是相同的,但 equals 是假的跨度>
-
如果您发布一个简短但完整的示例来演示问题,那将非常有帮助...
-
顺便说一句,一旦你弄清楚你的问题,你可能想修改你如何实现你的
hashCode()方法。连接字符串来计算哈希码比它需要的更昂贵。阅读here 了解其他想法。
标签: java equals contains hashcode hashset