2012-01-25 12 views
1

ListにはHashMapsが含まれています。リスト内の各HashMapには、複数のkey/valueペアが含まれている場合があります。私は、リストのindexOfに、HashMapで渡された要素のインデックスを調べたいと思います。しかし、問題は、e quals method of HashMapが比較中にすべてentrySetを見ることです。それは私が望むものではありません。複数のキーと値のペアを持つHas​​hMapを含むListでindexOfを使用する方法

例:

List<HashMap> benefit = new ArrayList<HashMap>(); 
    HashMap map1 = new HashMap(); 
    map1.put("number", "1"); 
    benefit.add(map1); 
    HashMap map2 = new HashMap(); 
    map2.put("number", "2"); 
    map2.put("somethingelse", "blahblah"); //1 
    benefit.add(map2); 

    HashMap find = new HashMap(); 
    find.put("number", "2"); 
    int index = benefit.indexOf(find); 
    if (index >= 0) 
     System.out.println(benefit.get(index).get("number")); 

上記のコードが原因//1でラインの何も印刷されません。

  • 上記のコードで実際に2が印刷されるようにするにはどうすればよいですか?
  • 自分自身を定義できるように、リストにcomparableを実装する方法はありますか?

    int index = myIndexOf(benefit, find); 
    
    ... 
    
    static int myIndexOf(List<HashMap> benefit, Map find) { 
        int i = 0; 
        for (Map map : benefit) { 
         Map tmp = new HashMap(map); 
         tmp.keySet().retainAll(find.keySet()); 
         if (tmp.equals(find)) { 
          return i; 
         } 
         i++; 
        } 
        return -1; 
    } 
    

    それは上書きされますリストの独自のサブクラスを宣言するために、もちろん、可能です:私はあなたがretainAll()を探していると思うので、あなたは、あなたが興味を持っている要素だけを比較することができ

+0

マイク、私はあなたが達成しようとしているかわからないんだけどそこに可能性があります少しのデザインの流れになります。たぶん、他のデータ構造がコードを単純化し、より効率的になるでしょう。あなたの目標は何ですか?何を保管していますか? – Gevorg

+0

渡されたHashMapに同じペアがある場合は?あるいは、「見つける」は常に1組にすぎず、どのインデックスにそのペアが含まれているかを見たいと思っていますか? – rtheunissen

+0

あなたは@Gevorgです。それは設計上の欠陥です。クラスのオブジェクトをハッシュマップではなくリストに格納しておけばいいと思います。それで私は自分の 'equals()'メソッドを公開することができました。しかし、レガシーコードがたくさんあるので、当面は 'HashMaps'で動作するソリューションを好むでしょう。 – Anthony

答えて

4

この動作のindexOfメソッドしかし、私はそれが良い考えだとは思わない。

:(o.equals(取得(I))== null)のO == nullのI(取得?)

が最も低いインデックスiように返します。それはindexOfメソッドの契約に違反します

これは、コードを管理している他の人にとっては紛らわしいものです。次に、HashMapをサブクラス化してequalsを再定義できると思うかもしれませんが、それはObject.equals()の対称性に違反します。

+0

retainAllについて知りませんでした! – Anthony

+0

コレクションではあまり知られていないものの1つです。共有してくれてありがとう。 +1 –

1

あなたの目標を達成しようとしている方法は間違っています。 indexOfメソッドは、この場合とまったく同じように動作します。部分一致ではなく完全一致を探しています。

あなたがしようとしていることは、正しく取得した場合、特定のエントリが含まれているマップのリストで地図を見つけることです。この場合は、すべてのマップを参照してcontainsKey()と呼んで検索を手動で実行し、検索すると予想される値とキーに関連付けられた値とを比較してください。

もう1つの方法は、Listの周囲にプロキシクラスを作成し、これを実行する新しいメソッドfindMapWithEntry (String key, String value)を追加することです(前述の同じ検索)。

0

indexOfメソッドはいつでもオーバーライドできます。 ArrayListのソースを見て:

public int indexOf(Object o) { 
    if (o == null) { 
     for (int i = 0; i < size; i++) 
     if (elementData[i]==null) 
      return i; 
    else { 
     for (int i = 0; i < size; i++) 
     if (o.equals(elementData[i])) 
      return i; 
    } 
    return -1; 
    } 

これは非常に複雑な検索アルゴリズムではありません。

List benefit = new ArrayList(){ 
public int indexOf(Object o){ 
     if (o == null) { 
     for (int i = 0; i < size; i++) 
     if (elementData[i]==null) 
      return i; 
     else { 
     for (int i = 0; i < size; i++) //traverse the hashmaps 
     Object key = ((HashMap)o).keySet().get(0); //assuming one pair 
     Object val = ((HashMap)o).valueSet().get(0); 
     if (
      ((HashMap)elementData[i]).containsKey(key) &&    
      ((HashMap)elementData[i]).get(key).equals(val)) 
       return i; 
     } 
     return -1; 
}; 

私のアドバイスは、おそらく独自のデータ構造を考えてみることです。

+1

しかし、それはmartielleが正しく指摘しているように、 'indexOf'の契約を破ります。 – Laf

+0

はい、そうですが、 'indexOf'の使用はここでは一般的ではなく、要件の外では使用されないと想定できます。だから、新しいクラスを作成することは有益でしょう。おそらく、 'indexOf'を再定義したArrayListを拡張してください。 – rtheunissen

+2

従来の方法でない場合は、期待される契約を実行する新しい方法を作成するほうが良いでしょう。メソッドの契約を変更するのは良いことではないと思うし、ジョシュ・ブロッホはその有効なJava_の本でその正確な点を述べている。 – Laf

0

検索方法を変更してみませんか?

List<Map> matchingBenefits = new ArrayList<Map>(); 
for (Map m : benefit) { 
    if (m.containsKey("number") && m.get("number").equals("2")) 
     matchingBenefits.add(m); 
} 
for (Map m : matchingBenefits) { 
    System.out.println(m.get("number")); 
} 
0

デザインを変更できない場合は、独自のメソッド検索ヘルプを作成しますか?

以下のコード私はあなたが何をしようとして理解し、それがOで実行されている場合(n)が動作するはず

public static String find(List<HashMap<String,String>> listMap, String key, String value) { 
    for(int i = 0; i < listMap.size(); i++) 
     if(listMap.get(i).get(key).equals(value)) 
      return value; 

    return null; 
} 
関連する問題