2017-02-05 8 views
2

まず最初に、私はかなり新しいプログラミングだと言いたいと思います。 スーパークラスのいくつかの "extends"を同じHashMapに格納します。 (例えば、XYとXZはXを拡張します - 私はX、XY、XZの両方を同じHashMapに格納します)。 私は便宜のためにこれを行うことに決めました。通常、何かをするたびに、 "X"に伸びるすべてのクラス(この例では "XY"と "XZ")が必要です。また、単一値がオブジェクトの指定された型のインスタンスであるかどうかをチェックしたい場合は問題ありません - 単に "instanceof"式を使用します。HashMapから一致するオブジェクトタイプを取得する

X objectoftypeX = hashmap.get(key) 
if(objectoftypeX instanceof XY){ 
    //do stuff 
} 

しかし、ここで私の質問が来る:どのように、XYのこのHashMapのでは、たとえば、のみを反復処理するのは、私は、キー「キー」の目的は「XY」のインスタンスであるかどうかを確認したいとしましょうか? 個々のオブジェクトを個別にチェックする必要はありませんか? このようにするのは理にかなっていますか? あなたは私の問題を理解することを願っています。

答えて

5

マップは、1つの形式のアクセス(キーによるルックアップ)を最適化するかなり単純な構造です。特定のタイプのアイテムをすばやく見つけるには、別の構造を使用する必要があります。例えば

、あなたは複数のマップを作成することを選択し、またはネストされたマップを作ることができます:

// Nested map, with the top level map indexing by Type (can be a String) 
// and the maps inside it indexing by a String key. 
Map<Type, Map<String, Object>> map = ...; 

あなたが個別にすべてのエントリをチェックするオーバーヘッドを気にしない場合、あなたは簡単にすべての要素あなたを得ることができますストリームにしたい:

List<XY> list = hashmap.values().stream() 
    .filter(v -> v instanceof XY) // check type 
    .map(v -> (XY) v) // do cast 
    .collect(Collectors.toList()); // collect to list 
2
hashmap.entrySet().filter(item -> item.value() instanceOf X).forEach(item -> ...); 

それは同じですが、shoter

+1

私はキーがX、XY、XZのタイプではないと思います。 – john16384

+0

ありがとう)ミスタイプで固定しました。 – dmitryvim

0
final Object[] keySetArray = mMap.keySet().toArray(); 
for(int x = 0; x < keySetArray.length; x++) 
{ 
     final Object whatStored = mMap.get(keySetArray[x]); 
     System.out.println("key[" + keySetArray[x] + "]: "+ whatStored); 
    // Make sure this check happens as it is, if you stored XY and XZ that extended X 
     if(whatStored instanceof of XY || whatStored instanceof XZ) 
     { 
      if(whatStored instanceof XY) 
      { 
        // Go here for instance X and XY 
      } 
      else if(whatStored instanceof XZ) 
      { 
       // Go here for instance X and XZ 
      } 
     } 
} 

希望はこちら閉じる??

+0

私はそれが近いと思っていますが、必要以上に複雑です。 –

0

標準のハッシュマップでは、これを効果的に(すべてを行なわずに)行うことはできません。ハッシュマップの目的は、わずかなメモリオーバーヘッドで、要素への高速アクセスを提供することです。整数サイズの配列と、格納されているオブジェクトごとに整数を返すhashcode関数があるとします。次に、index = hashcode(key)を適用して要素を見つけることができます。これは基本的には何かを見つける1つの操作です。しかし、あなたはひどいメモリオーバヘッドを持っています(配列の大きさはすべての整数に等しい)。

その他のオプションは、リストを持ち、すべての要素を通過することです。ここではメモリのオーバーヘッドはありませんが、検索の複雑さはO(n)になります。要素が配列内にない(または早く見つかる)ためにすべてを調べる必要があります。

ハッシュマップは中間にあります。サイズの配列を割り当てて100とすると、そのキーのハッシュコード関数が計算され、結果は105になります。したがって、オブジェクトをインデックス{hashcode_result}のモジュロarray_sizeに配置します。私たちの場合105%100 == 5

興味深いものは、同じポジションを持つkey2としての衝突がある場合、あなたが何をするかによって異なります。たとえば、ハッシュコード値が205,305の場合(これらのハッシュコードはすべてモジュロ5になります)。 これらの追加要素を次に利用可能なインデックス6,7に追加することも可能です はJavaで(あるいは、少なくとも私が覚えている限りでは)バケットは、リンクリストとして実装されているので、あなたは

0 => [] 
1 => [] 
2 => [] 
3 => [] 
4 => [] 
5 => [k=105, k=205, k=305...] 

ハッシュコード機能を実装することであろうあなたのユースケースのためのハッシュマップを使用する方法の唯一の方法がありますこれは常に同じクラスの同じハッシュを生成します。しかしこれはハッシュマップをn個のリストに縮退します。ここでnはサブクラスの数です。そして、正しく実装されたハッシュマップ(ハッシュコード値の一様な分布)が保証されている間、ルックアップはひどく苦しんでいるでしょう(値を調べるためにM/n演算をしなければなりません、Mは要素の数であり、nは別個のクラスの数です)ハッシュマップの構造を、あなたは効果的にデータ依存loopkupのいずれかのタイプを行うことができないので、あなたが検索にパフォーマンスを殺すウィル( - ルックアップの回数は1


かいつまんに効果的に等しくなりますリストを通して)。 このタイプの参照が必要な場合は、の回答はjohn16384です。本当に良いです。

関連する問題