比较通过id等于的对象的属性

时间:2016-01-27 16:16:36

标签: java unique equality

让我们假设有一个数据服务返回类cat的实例:

class Cat {
  int id;
  String name;
  int iq;
}

我希望将实例保存在Set<Cat>内,这些实例不能容纳两只具有相同ID的猫。因此,我需要覆盖equalshashcode方法,仅检查id

我的问题是,当我从具有相同ID但具有name和/或iq的不同值的服务收到新实例时,如何检测我的集合中的某些猫是否需要更新? ?我无法将属性添加到equalshashcode,因为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
  }
}

我想到的解决方案是:

  1. current.requiresUpdate(newCat) //basically copy of equals() with properties
  2. current.updateWith(newCat) //same as above but keeping the old instance
  3. if (!current.name.euqals(newCat.name)) //for each property
  4. 仅从服务中获取已更改的对象。最佳,但超出了我的范围。
  5. 所有这些都需要一些冗余的代码,这就是为什么我希望有一个模式或集合为我工作。
    解决方案可以包括番石榴类。

4 个答案:

答案 0 :(得分:2)

您只需要再次插入值。

如果id与之前的cat对象匹配,则会在set中覆盖。

HashSet在内部维护一个HashMap来识别重复项。

答案 1 :(得分:2)

我认为你有两个不同的问题:

  • 比较Cat个对象:如果Catidname相等,则两个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将有不同的nameiq

答案 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();