我有类ID和值,以及从ID到值的映射
public class IDs {
public TreeSet<Integer> ids;
public HashSet<IDs> neighbors;
public static HashSet<IDs> idSet = new HashSet<>();
private boolean hash;
private int hashcode;
public IDs(int id,HashSet<IDs> neighbors) {
this.ids = new TreeSet<>();
this.ids.add(id);
this.neighbors = neighbors;
idSet.add(this);
this.hash = false;
this.hashcode = 0;
}
public void addNeighbor(IDs neighbor) {
this.neighbors.add(neighbor);
neighbor.neighbors.add(this);
}
public static boolean cluster(IDs id1,IDs id2) {
if (id1.equals(id2))
return false;
id1.ids.addAll(id2.ids);
id2.ids.addAll(id1.ids);
id2.neighbors.remove(id1);
id1.neighbors.remove(id2);
id1.neighbors.addAll(id2.neighbors);
id2.neighbors.addAll(id1.neighbors);
id1.hash = false;
return true;
}
@Override
public String toString() {
String name = "{";
for (Integer i:ids)
name += "Cell " + i + ", ";
name += "}";
return name;
}
@Override
public boolean equals(Object obj) {
IDs o = (IDs) obj;
return this.ids.containsAll(o.ids) && o.ids.containsAll(this.ids);
}
@Override
public int hashCode() {
if (this.hash)
return this.hashcode;
TreeSet temp = (TreeSet) this.ids.clone();
int first,hash = 0;
while (!temp.isEmpty()) {
first = (int) temp.first();
temp.remove(temp.first());
hash = CantorPair(hash,first);
}
this.hash = true;
this.hashcode = hash;
return hash;
}
private int CantorPair(int k1,int k2) {
return (k1 + k2) * (k1 + k2 + 1) / 2 + k2;
}
}
class Value{
Integer value;
}
Map<ID,Value> map = new Map<>();
现在我想将条目合并在一起,新值是旧值的总和,但我创建的是具有重复键和旧值的条目。任何人都知道如何解决这个问题?
EDIT1:我已经覆盖了equals()
和hashCode()
,抱歉没有在此处显示,地图仍然有重复的密钥条目!
EDIT2:我已经上传了班级的完整代码
答案 0 :(得分:1)
当您的密钥类(hashCode()
)未覆盖equals(Object o)
和ID
方法时,Java只使用对内存中对象的实际引用(指针地址)来计算值(即检查它是否与类的实例化相同)。这就是你获得重复密钥的原因(Java&#34;认为&#34;所有结果都是唯一的。)
要解决此问题,您需要覆盖两种方法,equals()
和hashCode()
。
class ID {
private String id;
public String getId() { return id; }
public String setId(String id) { this.id = id; }
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
// safe cast to ID
ID test = (ID)obj;
// is id nullable? if so, you need to make an additional null-check here
return this.getId().equals(test.getId());
}
@Override
public int hashCode() {
// is id nullable? if so, you need to make an additional null-check here
return this.getId().hashCode();
}
}
请参阅Why do I need to override the equals and hashCode methods in Java?
上述代码可以帮助您将自定义类(ID)用作集合键。但我发现你的问题还有另一个问题:
现在我想将条目合并在一起,新值是旧值的总和,
请先尝试自己解决,如果你没有成功,请在这里发布一个显示你努力的问题。你的问题,正如它目前所写,并没有显示你所尝试的内容。
答案 1 :(得分:1)
用作Map
键的类需要以一致的方式覆盖hashCode
和equals
方法。 (简而言之,这意味着如果两个实例按照equals
方法相同,那么它们的hashCode
方法必须返回相同的值。)
您在equals
课程中既不会覆盖hashCode
也不会覆盖ID
,因此每当您将其用作地图的关键字时,您都会收到意外的结果。
根据值的合并,Map
中有一个merge
method,这绝对是您正在寻找的。如果您在sum
课程中使用了Value
方法,则可以按以下方式执行:
class Value {
Integer value;
Value sum(Value another) {
value += another.value;
return this;
}
}
Map<ID, Value> map = new HashMap<>(); // Map is an interface,
// you need an actual implementation
map.merge(someId, someValue, Value::sum);