2009-08-29 22 views
10

put関数は正常に動作しますが、get関数は正常に動作しません。どうやら私はそのトリックを知らない。MATLAB配列をHashMap Javaオブジェクトのキーとして使用するにはどうすればよいですか?

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

ans = [] 

私は多くの投稿を検索して読みましたが、この問題の解決策を見つけることができませんでした。 誰かが私にそのトリックを知らせることができればそれは素晴らしいことでしょう。

答えて

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のサブクラスを作成することができます。

+0

ありがとう。それは完璧に動作します! –

1

Javaハッシュマップのキーとして数値ベクトルや行列を使うことはできません。代わりに、ベクトルまたは行列を、ベクトルまたは行列の値の一意の文字列表現など、単一の一意のキーに変換する必要があります。

  • が整数配列の場合、あなたは、このように文字列を作成し、それらと同等のASCII表現に整数に変換するためにCHAR機能を使用することができます。これを行うには、いくつかの方法があります。この範囲外のものは未定義の動作をする可能性があるため、0〜65535の整数値に対してのみ有効です。あなたの代わりにINT2STRを使用することができ、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 
    

    :浮動小数点配列では、あなたは、フォーマットを作成するためにNUM2STR機能を使用することができます

    keyValue = int2str(X(:)'); 
    
  • ここでは一例です一緒に連結された各配列要素の文字列表現。ここでは例を示します。

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

    は(浮動小数点値の丸めを避けることによって)キーの一意性を確保するためには、代わりにDEC2BINを使用して、完全な64ビットのバイナリ表現にdouble型の値を変換することができます。

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

これらのオプションの一つの欠点は、あなたの鍵は潜在的にかなり長い文字列になってしまうかもしれないということです。しかし、これはおそらく巨大文字キーになります。キーの文字数に上限があるか、長い文字列をキーとして使用しているときにパフォーマンスが低下するかはわかりません。

+0

ありがとうございました。これは整数入力に対して有効です。 Matlabの行列からJavaオブジェクトを生成する方法はありますか? (例:1:.1:3) char関数もそれらの関数で動作しますが、単純に非整数部分を無視すると思います。 –

+0

もう一度ありがとうございます。それは非常に遅いですが、かなりうまく動作します。私がこれをやった理由は、効率的なA *アルゴリズムをmatlabに実装しようとしていることです。したがって、私は高速アクセスのためのJavaオブジェクトを使用していますが、私はC++コードを書いて、それをmexifyする方が良いと思われます。キャッチは、A *を可能な限り柔軟にしたいと思っています。例えば、すべての検索ドメイン仕様を入力機能として受け取る。 –

-1

最近のバージョンのMATLAB(2008b以降)を使用している場合、MATLABには、特定の種類のキーに対応する独自のマップクラスがあります。ドキュメントを参照してください:containers.Map

+0

残念ながら、Matlabのコンテナは行列をサポートしていません。 –

0

Matlabの構造体は、英数字キー([a-zA-Z] [a-zA-Z_0-9] *マッチング)から非常に高速な検索を提供します。あなたが数字からハッシュしようとしているなら、配列を2倍にしたまばらな配列を使うことをお勧めします。 arrayvalueは、あなたが検索しようとしているものにインデックスを指します。 hth

関連する問題