【问题标题】:Comparing properties of objects that equal through an id比较通过 id 相等的对象的属性
【发布时间】:2016-01-27 16:16:35
【问题描述】:

假设有一个数据服务返回类 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. 仅从服务中获取已更改的对象。最佳,但超出了我的范围。

所有这些都需要一些冗余代码,这就是为什么我希望有一个模式或集合可以为我工作。
解决方案可以包括 Guava 类。

【问题讨论】:

  • 您真的不希望集合中不包含两只具有相同 ID 的猫,还是不希望两只猫具有相同的 ID?如果是前者,请使用Map<Integer, Cat>,并在添加之前检查是否为map.containsKey(id)
  • 您可以将所有实例保存在 Map<Integer, Cat> 中,而不是 Set<Cat>。然后你仍然可以让你的equals() 方法检查猫是否相同。或者只是编写一个不同的方法来比较所有字段。实际上,无论如何你都必须这样做。

标签: java unique equality


【解决方案1】:

我认为你有两个明显的问题:

  • 比较Cat 对象:如果两个Cat 对象相等,则仅当idnameiq 相等时,然后相应地实现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】:

您只需要再次插入该值。

如果 id 将与之前的 cat 对象匹配,它将在集合中被覆盖。

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

【讨论】:

  • 我的问题不够具体。我已经更新它以表明一个简单的更新是不够的。
【解决方案3】:

更简单的解决方案是:如果发现相等 - 删除它并再次添加,并更新值。代码可能有点像这样:

yourSet.remove(cat);
yourSet.add(newCatObejectWithSameID);

newCatObejectWithSameID 将有不同的 nameiq

【讨论】:

  • 我的问题不够具体。我已经更新它以表明一个简单的更新是不够的。
【解决方案4】:

您的要求听起来有点奇怪 - 如果 ID 字段应该唯一标识 Cat,那么肯定应该只有一个具有该 ID 的 Cat 实例。或者,至少,多个Cat 实例上的对应字段应该相等。

然而,假设可以有多个逻辑上不同的Cat实例具有相同的ID,处理这个问题的最简单方法是使用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();

【讨论】:

  • 我认为问题说明了“集合中有一个实例,我从(某处)得到更新,我如何确定是否需要更新它”。只需更换它就可以轻松回答。一套似乎很好,除了它缺少replace 或添加只是添加它:/
  • 我的问题不够具体。我已经更新它以表明一个简单的更新是不够的。
猜你喜欢
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多