如何使用MATLAB数组作为HashMap java对象的键?

如何使用MATLAB数组作为HashMap java对象的键?,java,arrays,matlab,hashmap,Java,Arrays,Matlab,Hashmap,put函数工作正常,但get函数工作不正常。显然我不知道这个把戏 >> X = [ 1, 2, 3]; >> M = java.util.HashMap; >> M.put(X,1); >> M.get([1,2,3]) ans = [] 我已经搜索和阅读了很多帖子,但没有找到解决这个问题的方法。 如果有人能告诉我这个诀窍,那就太好了。我认为在Java hashmap中不能使用数字向量或矩阵作为键。相反,您必须将向量或矩阵转换为单个唯一键,例如

put函数工作正常,但get函数工作不正常。显然我不知道这个把戏

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

ans = []
我已经搜索和阅读了很多帖子,但没有找到解决这个问题的方法。
如果有人能告诉我这个诀窍,那就太好了。

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

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

ans = []
  • 对于整数数组,可以使用函数将整数转换为其等效的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
    
    X = rand(2,3)*9999;  % X is a 2-by-3 matrix of random double values
    keyValue = num2str(X(:)','%10.5f');
    
    对于太大而无法使用CHAR的整数值,可以使用:

  • 对于浮点数组,可以使用该函数为连接在一起的每个数组元素创建格式化字符串表示形式。下面是一个例子:

    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
    
    X = rand(2,3)*9999;  % X is a 2-by-3 matrix of random double values
    keyValue = num2str(X(:)','%10.5f');
    
    为了确保键的唯一性(通过避免浮点值的舍入),您可以使用将双精度值转换为完整的64位二进制表示形式。但是,这可能会导致大量字符密钥:

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

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

如果您使用的是较新版本的MATLAB(我认为是2008b或更高版本),则MATLAB有自己的map类,可用于某些类型的键。请参阅文档:

我认为问题在于Java原语数组没有为您提供正确的equals()和hashCode()。它们使用标准的对象方法,通过对象标识而不是包含的值进行比较。当使用非标量数组作为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子类来检查其输入键的类型,并在这个按值包装器中自动包装基元数组。

Matlab结构提供了非常快速的字母数字键查找(好的,[a-zA-Z][a-zA-Z_0-9]*匹配);否则,如果您试图从数字散列,我建议使用稀疏数组和数组加倍;让arrayvalue指向要查找的内容的索引。谢谢。这适用于整数输入。是否存在从Matlab矩阵生成java对象的方法?(例如:1:1:3)char函数也适用于它们,但我认为它只是忽略了非整数部分。再次感谢。它工作得很好,尽管速度很慢。我最终这样做的原因是我试图在matlab中实现一个高效的A*算法。因此,我使用java对象进行快速访问,但我最好写C++代码并使之省略。问题是,我想要一个尽可能灵活的。例如,接收所有搜索域规范作为输入函数。不幸的是,Matlab中的容器不支持矩阵。