2009-08-29 10 views

Respuesta

6

Creo que el problema es que las matrices primitivas de Java no proporcionan los iguales equals() y hashCode() para usted. Usan los métodos estándar de Object que se comparan por identidad de objeto en lugar de valores contenidos. Al usar matrices no escalares como claves en un HashMap, Matlab las convertirá en dobles [], pero serán objetos de Java distintos, por lo que obtendrán este comportamiento.

Si ha ajustado los valores de su matriz en un objeto Java que proporcionó un comportamiento de valor poro para equals() y hashCode() antes de usarlos como claves, esto podría funcionar. Afortunadamente, java.util.Arrays proporciona implementaciones de valor por defecto para las matrices primitivas. Solo tenemos que darles una caché en una clase contenedora que proporciona la interfaz que espera 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); } 
} 

Ahora puede envolverlos y utilizarlos como claves de 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) 

Esto funciona bajo R2008b para mí.

>> scratch_array_keyed_hashmap 
gotBack = 
my value 

Para facilitar su uso, se puede crear una subclase HashMap que comprueba el tipo de sus teclas de entrada, y automáticamente envuelto matrices primitivas en este envoltorio por valor.

estructuras
+0

Muchas gracias. ¡Funciona a la perfección! –

1

No creo que pueda usar vectores numéricos o matrices como claves en un hashmap de Java. En su lugar, tendría que convertir el vector o la matriz en una única clave única, como una representación de cadena de caracteres única de los valores en el vector o matriz. Hay algunas maneras de hacer esto:

  • Para matrices de enteros, se puede utilizar la función CHAR para convertir los números enteros a sus representaciones ASCII equivalentes, creando así una cadena de caracteres. Esto solo funcionará efectivamente para valores enteros entre 0 y 65535, ya que cualquier cosa fuera de este rango es probable que tenga un comportamiento indefinido. He aquí un ejemplo:

    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 
    

    Para valores enteros demasiado grandes para usar CHAR, puede utilizar INT2STR lugar:

    keyValue = int2str(X(:)'); 
    
  • Para las matrices de punto flotante, puede utilizar la función NUM2STR para crear un formateado representación de cadena de cada uno de los elementos de la matriz concatenados juntos. He aquí un ejemplo:

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

    para garantizar la unicidad de la clave (evitando de redondeo del valor de coma flotante) que en su lugar podría convertir los valores dobles a sus completas representaciones binarias de 64 bits utilizando DEC2BIN. Sin embargo, es probable que esto da lugar a enormes teclas de caracteres:

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

Un inconveniente de estas opciones es que las llaves podrían potencialmente llegar a ser cadenas de caracteres bastante largos. No estoy seguro de si hay un límite superior en el número de caracteres en la clave o si hay un golpe de rendimiento en el uso de cadenas de caracteres largos para las teclas.

+0

gracias. Esto funciona para entradas enteras. ¿Hay alguna forma de generar objetos java a partir de matrices Matlab? (por ejemplo, 1: .1: 3) La función char también funciona en ellos, pero creo que simplemente ignora las partes no enteras. –

+0

Gracias de nuevo. Funciona bastante bien, aunque es muy lento. La razón por la que terminé haciendo esto es porque estoy tratando de implementar un algoritmo A * eficiente en matlab. Por lo tanto, estoy usando objetos Java para un acceso rápido, pero parece que es mejor que escriba un código C++ y lo mexifique. El problema es que me gustaría tener A * lo más flexible posible. Por ejemplo, recibir todas las especificaciones del dominio de búsqueda como funciones de entrada. –

-1

Si está utilizando una versión más reciente de MATLAB (2008b o posterior, creo), entonces MATLAB tiene su propia clase de mapa que funciona para ciertos tipos de claves. Consulte la documentación: containers.Map

+0

Desafortunadamente, los contenedores en Matlab no admiten matrices. –

0

Matlab proporcionan operaciones de búsqueda muy rápido de teclas alfanuméricas (bueno, [a-zA-Z] [a-zA-Z_0-9] * de juego); Si eso no funciona, si intentas hacer hash a partir de los números, te sugiero que utilices arrays dispersos con doblaje de array; deje que el valor de matriz apunte al índice en lo que sea que intente buscar. hth

Cuestiones relacionadas