我这样初始化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()
方法未被正确覆盖。我认为我已经正确实现了这两个方法。
hashCode()
方法。将字符串连接起来计算哈希码比必要的代价更高。在这里阅读其他想法:https://dev59.com/oHVD5IYBdhLWcg3wBm1g。 - sstan