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