10

put 函数可以正常工作,但 get 函数不能。显然我不知道诀窍。

>> X = [ 1, 2, 3];
>> M = java.util.HashMap;
>> M.put(X,1);
>> M.get([1,2,3])

ans = []

我搜索并阅读了许多帖子,但找不到解决此问题的方法。如果有人可以让我知道诀窍,那就太好了。

4

4 回答 4

6

我认为问题在于 Java 原始数组没有为您提供正确的 equals() 和 hashCode()。他们使用标准的 Object 方法,通过对象标识而不是包含的值进行比较。当使用非标量数组作为 HashMap 中的键时,Matlab 会将它们转换为 double[],但它们将是不同的 Java 对象,因此它们会得到这种行为。

如果在将数组值用作键之前将数组值包装在为 equals() 和 hashCode() 提供按值行为的 Java 对象中,这可能会起作用。幸运的是,java.util.Arrays 为原始数组提供了按值实现。我们只需要将它们放在一个提供 HashMap 期望的接口的包装类中。

package test;
import java.util.Arrays;

/**
 * A double[] that with by-value semantics for equals() and hashCode() so you
 * can use it in HashMaps.
 * In a non-toy class, you'd probably use switch statements to support arrays
 * of any primitive type. In a language with real generics, you'd just template
 * this.
 */
public class EqualByValueDoubleArray {
    private double[] x;
    public EqualByValueDoubleArray(double[] x) { this.x = x; }
    public double[] getArray() { return x; };
    public boolean equals(Object obj) {
        if (obj instanceof EqualByValueDoubleArray) {
            return Arrays.equals(this.x, ((EqualByValueDoubleArray)obj).x);
        } else {
            return false;
        }
    }
    public int hashCode() { return Arrays.hashCode(x); }
}

现在您可以包装它们并将它们用作 Matlab 中的键。

function scratch_array_keyed_hashmap
import test.EqualByValueDoubleArray;
map = java.util.HashMap;
a = [1 2 3 4 5]';

key = EqualByValueDoubleArray(a);
map.put(key, 'my value');
% Separate key so we know it's comparing by value, not Java object identity
key2 = EqualByValueDoubleArray(a);
gotBack = map.get(key2)

这对我来说适用于 R2008b。

>> scratch_array_keyed_hashmap
gotBack =
my value

为了更方便使用,您可以创建一个 HashMap 子类来检查其输入键的类型,并在此按值包装器中自动包装原始数组。

于 2009-08-31T14:48:54.930 回答
1

我不认为您可以使用数字向量或矩阵作为 Java 哈希图中的键。相反,您必须将向量或矩阵转换为单个唯一键,例如向量或矩阵中值的唯一字符串表示。有几种方法可以做到这一点:

  • 对于整数数组,您可以使用CHAR函数将整数转换为其等效的 ASCII 表示,从而创建一个字符串。这仅对 0 到 65535 之间的整数值有效,因为超出此范围的任何内容都可能具有未定义的行为。这是一个例子:

    X = [1 2 3; 4 5 6];  % X is a 2-by-3 matrix
    keyValue = char(X(:)');  % Reshape X to a row vector and convert to ASCII
    

    对于太大而无法使用 CHAR 的整数值,您可以改用INT2STR

    keyValue = int2str(X(:)');
    
  • 对于浮点数组,您可以使用NUM2STR函数来创建连接在一起的每个数组元素的格式化字符串表示。这是一个例子:

    X = rand(2,3)*9999;  % X is a 2-by-3 matrix of random double values
    keyValue = num2str(X(:)','%10.5f');
    

    为了确保键的唯一性(通过避免浮点值的四舍五入),您可以使用DEC2BIN将双精度值转换为其完整的 64 位二进制表示。但是,这可能会导致巨大的字符键:

    keyValue = reshape(dec2bin(X(:),64)',1,[]);
    

这些选项的一个缺点是您的密钥可能最终成为相当长的字符串。我不确定键中的字符数是否有上限,或者使用长字符串作为键是否会影响性能。

于 2009-08-29T23:07:38.693 回答
0

Matlab 结构提供从字母数字键非常快速的查找(嗯,[a-zA-Z][a-zA-Z_0-9]* 匹配);失败了,如果你试图从数字中散列,我建议使用稀疏数组和数组加倍;让 arrayvalue 指向您要查找的任何内容的索引。hth

于 2009-08-31T18:06:35.040 回答
-1

如果您使用的是更新版本的 MATLAB(我认为是 2008b 或更高版本),那么 MATLAB 有自己的映射类,适用于某些类型的键。请参阅文档:containers.Map

于 2009-08-29T23:18:12.027 回答