【问题标题】:Update elements in an ArrayList using a HashMap that keeps track of the indexes使用跟踪索引的 HashMap 更新 ArrayList 中的元素
【发布时间】:2015-05-22 12:11:37
【问题描述】:

我正在实现一个队列类,其中的元素(使用 ArrayList 实现)应该是可更新的,并且我有一个 HashMap 实例变量来跟踪它们的索引,因此该函数不必遍历数组查找为要替换的对象。

我正在尝试这样做:

public void update(T oldElement, T newElement) {
    int index = map.get(oldElement);
    map.put(newElement, index);
    elements.set(index, newElement);
}

参数 oldElement 是对一个对象的引用,该对象肯定等于要替换的元素,但我意识到它们仍然是单独的对象,并且在我的 HashMap 中找不到 oldElement,因为它不是那里有一把钥匙。我真的想不出任何关于这个的想法,任何帮助都将不胜感激。

HashMap 如下所示:

private HashMap<T, Integer> map = new HashMap<T, Integer>();

编辑:方法更新由类外的代码调用。


已解决

这是由于我的 remove() 方法中的一个错误。我没有意识到 HashMap 实际上使用了对象的哈希值。

【问题讨论】:

  • 从地图中删除 index/oldElement 并在之后添加 index/newElement 有什么问题?
  • 您需要插入/删除方法,这些方法还会更新您的地图以使其与您的数组保持一致。
  • 当你说“一定要相等”时,你真的实现了自己的equals和hashCode方法吗?
  • 史蒂夫:我有。大家:是 remove() 方法中的一个错误导致了错误,我只是认为这是因为它们是不同的对象。我没有意识到 HashMap 在比较时实际上使用了对象的哈希值。 :/我需要睡觉。感谢您的宝贵时间!

标签: java arraylist hashmap


【解决方案1】:

您可以实现一个散列函数,而不是存储实际的键,而是存储散列,如果两个键值相等,则保证相等。这相当于在密钥类中实现.equals().hashCode(),但如果你不能这样做,那么这是一个可能的替代方案:

protected int calculateHash(T key) {
  // Your hash calculation is done here, the hash function must guarantee
  // that the hash value is equal when feed equal keys, for example
  // suppose that the key object contains a getName() method:
  return getName().hashCode();
}

并且使用方法来访问地图,而不是元素值本身:

map.put(calculateHash(newElement), index);

和:

map.get(calculateHash(element));

请注意,当关键对象发生变化时,您不需要更新映射(只要它产生与旧对象相同的哈希码),您只需要在索引发生变化时更新映射。

如果您能够在T 类中实现.hashCode().equals(),这一切都是不必要的。 Eclipse 或其他 IDE 可以自动为您生成这些方法。实现.hashCode().equals() 是所有处理集合的类的最佳实践,尤其是当您使用Sets 和Maps 时。

【讨论】:

  • 谢谢!原来我并不真正知道 hash 方法的用途,但它已经实现了。该错误是由于另一种方法中的错误造成的。
【解决方案2】:

为什么不简单地使用LinkedHashMap,它可以保证顺序,并且可以在 O(1) 中删除/获取。

您也可以简单地使用LinkedHashSet,如果您只想存储对象本身,而在伴随对象中没有辅助会计信息。

正如@EmirCalabuch 指出的那样,这两种解决方案(顺便说一句,您的解决方案也是如此)都要求同一个对象不会两次进入队列,并且对象已正确实现 equals 和 hashCode 方法。

【讨论】:

  • 这也是我的建议,但前提是对象类实现了.hashCode().equals(),否则它将不起作用。此外,该解决方案对对象施加了唯一性约束,而普通列表则没有。这不是对答案的批评,只是指出它也需要相等方法。
  • 这是一个优先队列,所以顺序不同。无论如何,我在另一种方法中发现了错误,我只是错误地认为这是由于对象不同(实际上我实现了 hashCode 和 equals 方法)。好吧,现在我知道哈希表是如何工作的了。谢谢你们的时间!
猜你喜欢
  • 2012-01-01
  • 2010-12-06
  • 2012-06-27
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
相关资源
最近更新 更多