web-dev-qa-db-ja.com

マップエントリセットの繰り返し

パラメータ化されたタイプがわからないマップのエントリセットを反復処理する必要があります。

そのようなエントリセットを反復するとき、なぜこれがコンパイルされないのですか?

public void myMethod(Map anyMap) {
    for(Entry entry : anyMap.entrySet()) {
        ...
    }
}

しかし、このコンパイル:

public void myMethod(Map anyMap) {
    Set<Entry> entries = anyMap.entrySet();
    for(Entry entry : entries) {
        ...
    }
}

これもコンパイルされます(マップのタイプがわからないので、これは使用できません)。

public void myMethod(Map<String, String> stringMap) {
    for(Entry<String,String> entry : stringMap.entrySet()) {
        ...
    }
}
17
Sergio

最初のエラーで発生するエラーは次のとおりです。

_Type mismatch: cannot convert from element type Object to Map.Entry
_

これは、コンパイラがFOR-INループを変換するためです。

_for (Entry entry : anyMap.entrySet()) {
}
_

に:

_for (Iterator i = anyMap.entrySet().iterator(); i.hasNext();) {
    Entry e = i.next(); // not allowed
}
_

2番目の例は動作しますただし、不正行為のみ!Setbackを取得するために未チェックのキャストを実行しています_Set<Entry>_に変換します。

_Set<Entry> entries = anyMap.entrySet(); // you get a compiler warning here
for (Entry entry : entries) {
}
_

になる:

_Set<Entry> entries = anyMap.entrySet();
for (Iterator<Entry> i = entries.iterator(); i.hasNext(); ) {
    Entry e = (Entry) i.next(); // allowed
}
_

更新

コメントで述べたように、コンパイラの生の型消去規則のため、両方の例で型情報が失われています。

下位互換性を提供するために、[〜#〜] all [〜#〜] rawタイプのインスタンスのメソッドは、erased対応するもの。したがって、Mapはrawタイプであるため、すべて消去されます。 Set<Map.Entry<K, V>> entrySet();メソッドを含める:生の型のインスタンスは、消去されたバージョンSet entrySet()を使用する必要があります。

23
David Lavender

これは、生のタイプMapを使用するためです。したがって、map.entrySet()は、パラメーター化されていないSetを取得します。これにより、Entryではなく、反復時にObjectが生成されます。

単純ですがエレガントな解決策は、Map <?、?>を使用することです。これにより、任意のMapを渡すことができますが、一方でmap.entrySet()の戻り値はSet <Entry>になります。

public void test(Map<?,?> map) {        
    for(Entry e : map.entrySet()){
        Object key = e.getKey();
        Object value = e.getValue();
    }       
}
6
Polygnome

最初の例では、map.entrySet()はSetを返します。ループで反復する場合は、Iteratorを使用します。設定されたコンテンツタイプに関する情報はないため、Javaオブジェクトは基本タイプであるためオブジェクトを使用し、コンパイラはオブジェクトをエントリに変換できないことを通知します。

Set<Map.Entry<K, V>> entrySet();

Rawマップタイプを使用する場合、entrySetはセットのみを返し、タイプ情報はありません。

2番目の例では、手動でSetをSet <Entry>に変換します(警告付き)。これでJavaはその中の内容を認識しているので、反復することができます。

最後の例ではマップタイプがわかっているため、entrySetは正しいタイプのセットを返し、タイプの規則なしで反復できます。

2
Leonidos

変数mapが存在しないため、最初のコードスニペットはコンパイルされません。パラメータanyMapを呼び出しましたが、mapとしてアクセスしようとしましたが、修正すると、rawtypes警告を除いてコードがコンパイルされます

1
Blank Chisui

私も同じ問題に直面しています。キャストに問題があるようです。以下のコードを試してみましたが、うまくいきました。

    for(Object entry : hashMap.entrySet())
    {
        System.out.println(((Entry<Object, Object>) entry).getKey() + " = " + ((Entry<Object, Object>) entry).getValue());

    }
0
user1696142

HashMapでタイプを指定していないため、コンパイル時間のエラーが発生しています

お気に入り

HashMap <(Integer,String> hm=new HashMap<(Integer,String>();  

タイプを整数および文字列として指定した場合、コンパイル時エラーは発生しません。

HashMapに追加する値がわからない場合は、次を使用します

HashMap<(Object,Object> hm=new HashMap();  
0
Ziyad