Итерируйте Hashmap Koloboke, изменяя его

У меня есть большой хэш-карта (~3M записей), и я использую Koloboke LongIntMap реализовать это. Мне нужно перебрать ключи на карте, но я могу изменить карту по пути. Некоторые из модификаций могут быть структурными (добавление / удаление записей).

Я не хочу платить цену за синхронизированные реализации или списки скопированных ключей, если это не является абсолютно необходимым. Я знаю, что результат итерации будет более или менее случайным, пропуская некоторые ключи, возможно, принимая другие ключи дважды, и в нашем приложении это не проблема.

Есть ли способ добиться такой итерации карты? Спасибо заранее за любые данные.

1 ответ

Решение

Идиоматический способ перебора коллекции 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));
}
Другие вопросы по тегам