1

大きなハッシュマップ (~3M エントリ) があり、KolobokeLongIntMapを使用して実装しています。マップ内のキーを反復処理する必要がありますが、途中でマップを変更できる必要があります。一部の変更は構造的なもの (エントリの追加/削除) である場合があります。

絶対に必要でない限り、同期された実装やコピーされたキーリストに代償を払いたくありません。反復の結果は多かれ少なかれランダムになり、一部のキーが省略されたり、他のキーが 2 回取得される可能性があることはわかっていますが、これはアプリケーションでは問題になりません。

そのようなマップの反復を達成する方法はありますか? ご意見をお寄せいただきありがとうございます。

4

1 に答える 1

2

Koloboke コレクションを変更 (キーの削除と更新、ただし追加ではない) で反復処理する慣用的な方法は、次のcursorとおりです。

for (LongIntCursor cur = map.cursor(); cur.moveNext();) {
    long key = cur.key();
    int value = cur.value();
    if (checkSomething(key, value)) {
        cur.remove(); // remove the entry
    } else {
        cur.setValue(newValue); // update the value
    }
}

ConcurrentModificationException追加はサポートされていません。これは、行うのと同じ方法で をスローする必要がjava.util.HashMapあります。その理由は、追加によって完全なマップの再ハッシュがトリガーされると、イテレーションを適切に終了できないからです。

回避策として、反復中にマップに挿入するエントリを収集し、反復後に一括挿入を実行できます。

// You could get primitive lists from fastutil, gs, hppc or trove
LongList keysToPut = keysToPutThreadLocal.get();
keysToPut.clear();
IntList valuesToPut = valuesToPutThreadLocal.get();
valuesToPut.clear();

for (LongIntCursor cur = map.cursor(); cur.moveNext();) {
    long key = cur.key();
    int value = cur.value();
    if (checkSomething(key, value)) {
        cur.remove(); // remove the entry
    } else {
        // want to insert a <newKey, newValue> entry
        keysToPut.add(newKey);
        valuesToPut.add(newValue);
    }
}
// bulk insert
for (int i = 0, toPut = keysToPut.size(); i < toPut; i++) {
    map.put(keysToPut.get(i), valuesToPut.get(i));
}
于 2015-08-31T18:25:53.477 に答える