Java 如何以二维int数组为键搜索HashMap

Java 如何以二维int数组为键搜索HashMap,java,Java,我有很多二维整数数组(大小为8x8),每个数组都有一些基于计算的双精度数值。我希望将它们存储在一个数据结构中,这样我就能够查找二维数组,并检查我之前给该数组的值 我一直在尝试使用二维数组的哈希代码,但并没有成功。 我还尝试使用数组作为键的hashMap,并尝试创建自定义对象作为键。但这两个都不适合我,所以我做错了什么。在哪里可以找到解决方案?不要使用数组,而是使用列表并使用带有hashCode作为键的映射。根据,如果列表中的值相同,则每次都应获得相同的值。哈希代码由以下公式计算 int hash

我有很多二维整数数组(大小为8x8),每个数组都有一些基于计算的双精度数值。我希望将它们存储在一个数据结构中,这样我就能够查找二维数组,并检查我之前给该数组的值

我一直在尝试使用二维数组的哈希代码,但并没有成功。
我还尝试使用数组作为键的hashMap,并尝试创建自定义对象作为键。但这两个都不适合我,所以我做错了什么。在哪里可以找到解决方案?

不要使用数组,而是使用
列表
并使用带有hashCode作为键的映射。根据,如果列表中的值相同,则每次都应获得相同的值。哈希代码由以下公式计算

int hashCode = 1;
  Iterator<E> i = list.iterator();
  while (i.hasNext()) {
      E obj = i.next();
      hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  }
int hashCode=1;
迭代器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()
对于任意两个列表,
list1
list2
, 按照
Object.hashCode()
总合同的要求


不要使用数组,而是使用
列表
并使用hashCode作为键的映射。根据,如果列表中的值相同,则每次都应获得相同的值。哈希代码由以下公式计算

int hashCode = 1;
  Iterator<E> i = list.iterator();
  while (i.hasNext()) {
      E obj = i.next();
      hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  }
int hashCode=1;
迭代器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()
对于任意两个列表,
list1
list2
, 按照
Object.hashCode()
总合同的要求


由于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

由于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

如果您使用的是阵列的相同实例,则只需将它们用作键,而无需执行任何操作:

@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<MyKey, Double> map = new HashMap<>();
    map.put(new MyKey(arr1), 5.7);
    Double val = map.get(new MyKey(arr2));

    assert val == 5.7;
}
@测试
公共无效测试2(){
整数[][]arr1=新整数[8][];
整数[][]arr2=新整数[8][];

对于(int i=1;i如果您使用的是数组的相同实例,则可以将它们用作键,而无需执行任何操作:

@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<MyKey, Double> map = new HashMap<>();
    map.put(new MyKey(arr1), 5.7);
    Double val = map.get(new MyKey(arr2));

    assert val == 5.7;
}
@测试
公共无效测试2(){
整数[][]arr1=新整数[8][];
整数[][]arr2=新整数[8][];

对于(int i=1;i)如果您的2D数组很小,大小一致,并且不是,那么通过使用1D数组并通过偏移量访问“内部”数组,您将获得更好的性能,“但这两种方法都不适用于我”然后编辑问题并向我们展示您的尝试,这样我们就可以帮助您找出错误所在。如果您的二维阵列很小,大小一致,而且不正确,那么使用一维阵列并通过偏移量访问“内部”阵列将获得更好的性能,“但这两种方法都不适用于我”然后编辑问题并向我们展示您尝试过的内容,这样我们可以帮助您找出错误所在。对于
List
,hashcode被设置为
List.hashcode()
“使用以hashcode为键的映射”为什么不使用
列表
本身作为键呢?请记住,hashcodes不能保证唯一,因此如果仅使用hashcode作为键,则会发生冲突。@Andreas HashMap使用
hashcode()
方法来散列对象。因此两者都是相同的。没有散列码,就无法在Java中维护映射。我知道,但是如果您的键是
列表,则映射可以有两个具有相同散列码的不同列表。如果您的键只是散列码,而不是列表本身,则不能有两个恰好具有相同散列码的不同列表e相同的hashcode。但是,
HashMap
可以存储两个非
equals()()
“使用hashCode作为键的映射”为什么不使用
列表本身作为键?请记住,hashcodes不能保证是唯一的,因此如果仅使用hashCode作为键,则会发生冲突。@Andreas HashMap使用
hashCode()
方法来散列对象。因此两者都是相同的。没有散列码,就无法在Java中维护映射。我知道,但是如果您的键是
列表,则映射可以有两个具有相同散列码的不同列表。如果您的键只是散列码,而不是列表本身,则不能有两个恰好具有相同散列码的不同列表e相同的hashcode。但是,
HashMap
可以存储两个非
equals()