让我们假设有一个数据服务返回类cat
的实例:
class Cat {
int id;
String name;
int iq;
}
我希望将实例保存在Set<Cat>
内,这些实例不能容纳两只具有相同ID的猫。因此,我需要覆盖equals
和hashcode
方法,仅检查id
。
我的问题是,当我从具有相同ID但具有name
和/或iq
的不同值的服务收到新实例时,如何检测我的集合中的某些猫是否需要更新? ?我无法将属性添加到equals
或hashcode
,因为Set可能会保存相同ID的实例。
我是否必须手动比较所有字段,还是有另一种典型的Java解决方案?
编辑以澄清:
仅使用新实例更新Set
是不够的,因为更新时会触发代码。所以我想做的是:
if (set.contains(newCat)) {
Cat current = set.get(newCat);
if (!current.equals(newCat)) { //obviously this is not enough
set.add(current);
//notify EventBusses and such
}
}
我想到的解决方案是:
current.requiresUpdate(newCat) //basically copy of equals() with properties
current.updateWith(newCat) //same as above but keeping the old instance
if (!current.name.euqals(newCat.name)) //for each property
所有这些都需要一些冗余的代码,这就是为什么我希望有一个模式或集合为我工作。
解决方案可以包括番石榴类。
答案 0 :(得分:2)
您只需要再次插入值。
如果id与之前的cat对象匹配,则会在set中覆盖。
HashSet在内部维护一个HashMap来识别重复项。
答案 1 :(得分:2)
我认为你有两个不同的问题:
Cat
个对象:如果Cat
,id
和name
相等,则两个iq
个对象相等,而不是相应地实现equals
方法。Cat
个对象的集合:要维护Cat
个对象的集合,其中没有两个对象具有相同的id
,请使用Map<Integer, Cat>
正如已经建议的那样。您的代码可能如下所示:
if (mapOfCats.contains(newCat.id)) {
Cat current = mapOfCats.get(newCat.id);
if (!current.equals(newCat)) {
mapOfCats.put(newCat.id, newCat);
// notify EventBusses and such
}
}
答案 2 :(得分:0)
更简单的解决方案是:如果发现相等 - 删除它并再次添加,使用更新的值。代码可能有点像这样:
yourSet.remove(cat);
yourSet.add(newCatObejectWithSameID);
newCatObejectWithSameID
将有不同的name
和iq
。
答案 3 :(得分:0)
您的要求听起来有点奇怪 - 如果ID字段应该唯一地标识Cat
,那么肯定只有Cat
具有该ID的单个实例。或者,至少,多个Cat
实例上的相应字段应该相等。
但是,假设可以是具有相同ID的多个逻辑上不同的Cat
个实例,处理此问题的最简单方法是使用Map<Integer, Cat>
:
Map<Integer, Cat> cats = new HashMap<>();
for (Cat cat : getAllCats()) {
if (!cats.containsKey(cat.id)) {
cats.put(cat.id, cat);
} else {
// Do whatever - ignore, log a message, throw an exception?
}
}
Collection<Cat> catsWithUniqueIds = cats.values();