2017-11-19 3 views
0

カスタムシリアライザで以前に見たオブジェクトを追跡するアイデンティティハッシュマップを使用しています。私はマップ内のエントリを繰り返し処理しようとするwhileループを持っています。メソッド呼び出し中に、addAllFieldsがオブジェクトのマップのキーセットに追加される可能性があります。いくつかのデバッグの後で私は、iterator.hasNext()が、最後のループ本体の実行以来、オブジェクトがマップに追加されたという事実を知っていても、falseを返すことに気付きました。私はここで間違って何をしていますか?Java ListイテレータがIdentityHashMapで動作しない

public Document serialize(Object obj) throws Exception { 
    reset(); 
    addToMap(obj); 
    Set<Object> keys = map.keySet(); 
    Iterator<Object> iterator = keys.iterator(); 
    while(iterator.hasNext()) { 
     Object key = iterator.next(); 
     Element objectElement = createObjectElement(key.getClass().getName(), map.get(key)); 
     addAllFields(objectElement, key); 
     document.getRootElement().addContent(objectElement); 
    } 
    return document; 
} 
+2

* "ここで間違っています? "*イタレーション中にマップを変更するng。 ['keySet()'](https://docs.oracle.com/javase/9​​/docs/api/java/util/IdentityHashMap.html#keySet--)のJavadocによると、*マップが**の場合セットの反復**が進行中に変更されたとき、反復の結果は** undefined **です。* – Andreas

+0

このような未定義の動作がないことが分かっている別のハッシュマップがありますか? –

+1

['ConcurrentHashMap'](https://docs.oracle.com/javase/9​​/docs/api/java/util/concurrent/ConcurrentHashMap.html)。 ['keySet()'](https://docs.oracle.com/javase/9​​/docs/api/java/util/concurrent/ConcurrentHashMap.html#keySet--)のJavadocは次のように述べています:*ビューのイテレータとスプライテータ[弱く一貫性があります](https://docs.oracle.com/javase/9​​/docs/api/java/util/concurrent/package-summary.html#Weakly)*つまり、構築時に存在していた要素をトラバースすることが保証されています正確に1回であり、施工後の変更を反映することがありますが、保証はできません。 – Andreas

答えて

0

あなたがListIteratorを使用する必要がある、とあなたも追加された要素を反復処理したい場合、あなたは逆に全体のことを実行する必要があります。あなたはあなたがキーセットラップする必要があるかもしれません

ListIterator<Object> iter = keys.listIterator(keys.size()); 
while (iter.hasPrevious()){ 
    Object prev=iter.previous(); 
    // do your Element creation here 
    // then use the iter.add() method 
    iter.add(/*new object*/); 
} 

NBすべてのListIteratorをサポートしていない異なるコレクション型で、おそらく#addAllFields()の引数としてiterを渡す必要があります keySetではなくエントリセットを反復処理する必要があります

+0

あなたの潜在的なソリューションに感謝します。何らかの並べ替えを保証する別のマップ実装を使用する必要があるためですか?リンクハッシュマップはどうですか? –

+1

私は正確な解決策は、あなたが#addAllFields()で追加したものが処理されたときにそれ以上の項目を追加できるかどうかによって異なりますか?私は、繰り返しの間に追加をサポートするMap実装はないと思います。 List > l = new ArrayList <>(map.entrySet()); // Vはマップ値の型です ListIterator > iter = l.listIterator(); そして、私の答えで上記のように。最後に 'map'が本当に更新される必要があれば、' l'から新しいエントリを追加する必要があります – SteveR

関連する問題