【问题标题】:How to use an Object array as a key in hashmap如何使用 Object 数组作为 hashmap 中的键
【发布时间】:2020-10-14 23:22:37
【问题描述】:

我有一个名为 Position[] 的对象数组,它返回一个 Position 对象数组。我想将其用作以下哈希图的键:HashMap<Position[],Double> h = new HashMap<>();

我了解即使元素相同,数组也具有不同的哈希码。所以我继续尝试覆盖equals和hashcode。这是我的尝试:

public class Key {
    private Position p1;
    private Position p2;

    public Key(Position p1, Position p2){
      this.p1 = p1;
      this.p2 = p2
    }

    @Override
    public boolean equals(Object object) {
      if (!(object instanceof Key)) {
        return false;
      }

      Key newKey = (Key) object;
      return this.hashCode()== newKey.hashCode(); //bit of a hack way
    }

    @Override
    public int hashCode(){
      int result = 17;
      result = 31 * result + this.p1.hashCode();
      result = 31 * result + this.p2.hashCode();
      return result;
    }
  }

所以我不得不将我的地图更改为HashMap<Key,Double> 但是,当我使用键获取值时仍然返回 null。

G2 G4E4 E6 ETC 可以传递给 Key 的构造函数的示例。

我将如何实现这一点,以便比较真正起作用?

谢谢。

【问题讨论】:

  • this.hashCode()== newKey.hashCode() ← 那最终会失败。只需使用 List<Position> 而不是数组。数组没有有用的哈希码,但列表是 guaranteed 以根据其元素的哈希码拥有哈希码。
  • 如果不能用List代替数组,可以使用实用类方法Arrays.hashCode得到正确的hashcode
  • @VGR ArrayList<Position> 可能吗?或者必须是List<Position>
  • 创建 ArrayList 时,可以将其称为 List、Collection、Iterable 或 Object。使变量和字段具有 List 或 Collection 而不是 ArrayList 的类型是一种很好的做法,因为 List 有许多可能的实现(例如 LinkedList 和 Arrays.asList),并且您希望可以选择使用它们。毕竟,你并不需要你的 List 是一个 ArrayList 才能使用它的方法。
  • 正确。 Java SE 中的所有 List 实现都已经正确实现了这些方法。

标签: java artificial-intelligence


【解决方案1】:

您可以创建一个特殊的包装对象以使用Position[] 作为Map 中的键,在equals(Object)hashCode() 的实现中使用Arrays.deepEquals(Object[], Object[])Arrays.deepHashCode(Object[])

import java.util.Arrays;

public final class PositionArrayKey {
    private final Position[] array;

    public PositionArrayKey(Position[] array) {
        this.array = array;
    }

    @Override
    public boolean equals(Object object) {
        if (object == this) return true;
        if (!(object instanceof PositionArrayKey)) return false;
        return Arrays.deepEquals(this.array, ((PositionArrayKey) object).array);
    }

    @Override
    public int hashCode() {
        return Arrays.deepHashCode(this.array);
    }
}

这可以在包装时将Position[] 数组实例作为键存储在映射中。例如

Map<PositionArrayKey, Object> map = new HashMap<>();
map.put(new PositionArrayKey(new Position[]{...}), ...);
Object value = map.get(new PositionArrayKey(new Position[]{...}), ...);

(假设在此示例中两个 Position[] 数组完全相等)

请注意,对于大型数组,调用 equals(Object)hashCode() 的性能可能会很慢。如果你觉得有必要,你可以修改上面的 sn -p 来缓存结果Arrays.deepHashCode(this.array) 用于更大的数组。

【讨论】:

  • 我认为您的意思是“可能很慢”而不是“可能不会很慢”,是吗?
  • @Steve 是的,是一个错字。已修复,谢谢指出。
猜你喜欢
  • 2015-05-11
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 1970-01-01
  • 2010-11-08
相关资源
最近更新 更多