我已经实现了我的多个密钥类,如下所示:
public class ProbabilityIndex {
private int trueLabel;
private int classifiedLabel;
private int classifierIndex;
public ProbabilityIndex(int trueLabel, int classifiedLabel, int classifierIndex) {
this.trueLabel = trueLabel;
this.classifiedLabel = classifiedLabel;
this.classifierIndex = classifierIndex;
}
@Override
public boolean equals(Object obj) {
if ( !obj instanceof ProbabilityIndex)
return false;
if (obj == this)
return true;
ProbabilityIndex rhs = (ProbabilityIndex) obj;
return new EqualsBuilder().
append(trueLabel, rhs.trueLabel).
append(classifiedLabel, rhs.classifiedLabel).
append(classifierIndex, rhs.classifierIndex).
isEquals();
}
@Override
public int hashCode() {
int hashCode = new HashCodeBuilder(17, 31).
append(trueLabel).
append(classifiedLabel).
append(classifierIndex).
toHashCode();
return hashCode;
}
}
请注意trueLabel
,classifiedLabel
和classifierIndex
都是0或1。
然后,我按如下方式使用我的密钥:
ProbabilityIndex key = new ProbabilityIndex(trueLabel, classifiedLabel, classifierIndex);
probabilities.put(key, new Double(value));
其中probabilities
声明如下:
HashMap<ProbabilityIndex, Double> probabilities;
但是,trueLabel
,classifiedLabel
和classifierIndex
的不同组合会将元组写入probabilities
中的相同位置,从而覆盖现有元组。
我如何克服这个问题?
最小测试用例:
HashMap<ProbabilityIndex, Double> map = new HashMap<ProbabilityIndex, Double>();
map.put(new ProbabilityIndex(0, 0, 0), new Double(0.1));
map.put(new ProbabilityIndex(0, 0, 1), new Double(0.2));
map.put(new ProbabilityIndex(0, 1, 0), new Double(0.1));
map.put(new ProbabilityIndex(0, 1, 1), new Double(0.2));
map.put(new ProbabilityIndex(1, 0, 0), new Double(0.1));
这会插入4个元组而不是5个。
答案 0 :(得分:3)
我只能告诉你,哈希表永远不会覆盖具有相同哈希码的对象(哈希冲突);它的检索效率会降低。
错误地覆盖条目的唯一方法是为密钥提供equals
方法,为不同的密钥返回true
。
一些与你的问题没有直接关系的进一步建议:如果你只有三个双状态变量,那么该类的完整值集的基数只有8而不是你使用的复杂的哈希码构建器,你可以用三个位构造哈希码,每个位代表一个变量。这将明确地确保对象的每个状态都有一个不同的哈希码。
我已使用hashCode()
和equals()
的以下实现验证了您的代码(我必须更改equals
以使您的示例真正自包含):
@Override public boolean equals(Object obj) {
if (!(obj instanceof ProbabilityIndex)) return false;
if (obj == this) return true;
ProbabilityIndex rhs = (ProbabilityIndex) obj;
return this.trueLabel == rhs.trueLabel
&& this.classifiedLabel == rhs.classifiedLabel
&& this.classifierIndex == rhs.classifierIndex;
}
@Override public int hashCode() {
return trueLabel | (classifiedLabel << 1) | (classifierIndex << 2);
}
您的测试代码生成了一个包含五个条目的地图。
作为最后一点,如果最大大小只有8,你甚至不需要一个哈希表。一个大小为8的普通数组,用上面的哈希码索引,就足够了。