如何通过使用HashMap的2维int数组作为键搜索

问题描述 投票:1回答:3

我有很多二维整数阵列(8×8尺寸),其各自具有基于计算一些数值双精度值的。我想将它们存储在数据结构,这样我就可以查找一个二维数组,并检查我已经给这个数组前面什么价值。

我一直在尝试使用二维数组,没有工作的一个hashCode。我也曾尝试将数组作为一个关键HashMap和我试图创建自定义对象作为键。但无论是制定了我,所以我做了什么。在哪里可以找到解决办法吗?

java
3个回答
1
投票

由于Java数组不从hashCode()机实现覆盖euqals()Object他们是不是真的适合查找。例如两个相同的阵列是不相等的:

int[][] a1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] a2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
System.out.println(a1.hashCode()); // 1277181601
System.out.println(a2.hashCode()); // 41903949
System.out.println(a1.equals(a2)); // false

然而,人们可以创建一个内部使用Arrays.deepHashCode()Arrays.deepEquals()如下的包装类:

public class IntIntArray {
  private int[][] values;

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    IntIntArray that = (IntIntArray) o;
    return Arrays.deepEquals(value, that.value);
  }

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

这个类是合适的用于基于值查找并可以用作Map键:

IntIntArray i1 = new IntIntArray(new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
IntIntArray i2 = new IntIntArray(new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
System.out.println(i1.hashCode()); // 30729379
System.out.println(i2.hashCode()); // 30729379
System.out.println(i1.equals(i2)); // true

0
投票

如果您使用的阵列相同的实例,你可以用它们作为而不做任何事情的关键:

@Test
public void test1() {
    Integer[][] arr = new Integer[8][];

    for (int i = 1; i <= 8; i++) {
        arr[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
    }

    Map<Integer[][], Double> map = new HashMap<>();
    map.put(arr, 5.7);
    Double val = map.get(arr);

    assert val == 5.7;
}

你可以在这里看到正从地图中的值,使用用于把它在同一个阵列,将返回需要的值。

这是因为哈希码数组的实施,等于是检查相同的实例,这也是不错的表现的,如果这是你的情况。

但是,如果你有相同的阵列(键)是行不通的不同实例:

@Test
public void test2() {
    Integer[][] arr1 = new Integer[8][];
    Integer[][] arr2 = new Integer[8][];

    for (int i = 1; i <= 8; i++) {
        arr1[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
        arr2[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
    }

    Map<Integer[][], Double> map = new HashMap<>();
    map.put(arr1, 5.7);
    Double val = map.get(arr2);

    assert val == null;
}

相反,你需要创建一个“重点”对象,并实施平等和哈希代码吧:

class MyKey {
    Integer[][] arr;

    public MyKey(Integer[][] arr) {
        this.arr = arr;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyKey myKey = (MyKey) o;
        return Arrays.deepEquals(arr, myKey.arr);
    }

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

并使用它:

@Test
public void test2() {
    Integer[][] arr1 = new Integer[8][];
    Integer[][] arr2 = new Integer[8][];

    for (int i = 1; i <= 8; i++) {
        arr1[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
        arr2[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
    }

    Map<MyKey, Double> map = new HashMap<>();
    map.put(new MyKey(arr1), 5.7);
    Double val = map.get(new MyKey(arr2));

    assert val == 5.7;
}

-1
投票

代替使用一个阵列,使用List<List<Integer>>并使用地图的hashCode作为键。由于每Java Documentation你应该得到相同的值,如果每次在列表中的值相同。哈希码是通过以下计算。

int hashCode = 1;
  Iterator<E> i = list.iterator();
  while (i.hasNext()) {
      E obj = i.next();
      hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  }

它还提到

这确保了list1.equals(list2)意味着list1.hashCode()==list2.hashCode()对于任何两个列表,list1list2所要求的Object.hashCode()的总承包合同。

© www.soinside.com 2019 - 2024. All rights reserved.