在Java中使用数组作为哈希键?

时间:2015-02-22 23:31:13

标签: java hashmap

我有一个可以进行一些计算的函数。它接受一个int数组,并根据传递给它的int数组的内容返回一个整数。

由于我的应用程序正在进行数百个这样的计算,我正在尝试设置一种方法将这些计算结果存储在一个hashmap中,这样就不必重新计算它最近已经完成的计算。为此,我需要使用int数组作为hashmap的键。

目前这是打印尺寸2,我希望它是打印尺寸1:

LinkedHashMap hashmap = new LinkedHashMap();

int test[] = {1,2,3};
int test2[] = {1,2,3};

hashmap.put(test, 1);
hashmap.put(test2, 1);

System.out.println("Size: "+hashmap.size());

实现这一目标的最佳方法是什么?我可以创建一个方法将数组转换为某种编码数组数据的字符串,但我认为这不是最好的解决方案。

4 个答案:

答案 0 :(得分:3)

它当前正在打印2,因为它们是两个不同的数组,有两个不同的hashCodes,所以尽管它们具有相同的元素,但它们对于集合的目的而言并不相同。您应该创建自己的对象,该对象在Object内部有一个数组作为变量。然后它将覆盖equals和hashCode方法,以便根据数组中的值使值相同。

e.g:

 public class MyClass
 {
        private int[] array;

       public boolean equals(Object o)
       {
           if(! (o instance of MyClass) ) return false;
           //loop through the arrays to see they are equal
         }

        public int hashCode()
       {  
           //loop through the array and return a number that is based off of the values in the array such as array[0] ^ array[1] + array[2] * array[3] / array[4] ...

        }
 }

答案 1 :(得分:0)

我会创建数组特定的密钥,然后将密钥和计算结果存储在缓存中:

public static void main() {
   Map<String, Integer> hashmap = new HashMap<>();
   int[] arr1 = {1, 2, 3};
   int[] arr2 = {1, 2, 3};
   hashmap.put(Arrays.hashCode(arr1), 1);
   hashmap.put(Arrays.hashCode(arr2), 1);
   System.out.println("Size: "+hashmap.size());
}

代码打印尺寸:1

答案 2 :(得分:0)

使用Apache commons StringUtils.join()方法创建唯一的数组键。它将数组作为参数,并在每个元素上调用toString()以获取每个元素的字符串表示形式。然后将每个元素字符串表示连接成一个字符串,如果指定了一个字符串,则在它们之间使用分隔符:

import org.apache.commons.lang3.StringUtils;

int[] a = {1, 2, 3}
String key= StringUtils.join(a, '-');
System.out.println(key);

产地:

1-2-3

答案 3 :(得分:0)

正如其他人所建议的那样,你应该创建一个包装数组的类,并以一致的方式实现hashCode()equals()

其他答案建议您将int[]数组转换为String,或者指示您应该迭代它以计算哈希值或检查相等性。

我建议您使用Java's Arrays实用程序类来有效地计算基于数组的哈希值并检查数组是否相等:

public class Key {

    private final int[] values;

    public Key(int[] values) {
        this.values = values;
    }

    @Override
    public boolean equals(Object another) {
        if (another == this) {
            return true;
        }
        if (another == null) {
            return false;
        }
        if (another.getClass() != this.getClass()) {
            return false;
        }
        Key key = (Key) another;
        return Arrays.equals(this.values, key.values);
    }

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

然后,在地图中使用它:

Map<Key, Integer> map = new LinkedHashMap<>(); // preserve insertion order?

int test[] = {1, 2, 3};
int test2[] = {1, 2, 3};

Key key = new Key(test);
Key key2 = new Key(test2);

map.put(key, 1);
map.put(key2, 1);

map.size(); // 1

注意: Key的此实现会考虑数组的元素顺序,这意味着两个Key如果从两个具有不同顺序的相同元素的数组

int[] v1 = {1, 2, 3};
int[] v2 = {2, 1, 3};

Key k1 = new Key(v1);
Key k2 = new Key(v2);

k1.equals(k2); // false!

如果您希望两个Key尽管数组的元素顺序相同,则应将int[]数组转换为HashSet中的Key类的构造函数,然后通过委派Key中各自的实现来实现equals()的{​​{1}}和hashCode()方法。