Как добавить элемент в HashSet во время итерации этого HashSet? - PullRequest
1 голос
/ 14 марта 2020

У меня есть сценарий использования, подобный следующему:

SET is a Set of Integer with size N
for i in SET (I mean only iterate the Set of size N at start point):
    if i + 7 not in SET:
        SET.add(i + 7)

return SET

Как реализовать это с помощью Java HashSet, кроме использования вспомогательного списка / набора для хранения элемента, который необходимо вставить?

Ответы [ 3 ]

3 голосов
/ 14 марта 2020

Невозможно добавить что-либо к экземпляру Set при переборе его содержимого; при использовании foreach l oop (for( var e : set ) запись) никакие модификации не допускаются, а при использовании явного итератора (for( var i = set.iterator(); i.hasNext(); ) … запись) вы можете вызвать i.remove(), чтобы избавиться от текущего элемента. Но добавление новых элементов в этом случае все еще не работает.

Это поведение является общим для всех Java Классов коллекции, хотя List знает специальный класс итератора, ListIterator, который также позволяет добавлять записи ( запись for( var i = list.listIterator(); i.hasNext(); ) …) по телефону i.add() - спасибо @lucasvw за напоминание об этом.

2 голосов
/ 14 марта 2020

@ lucasvw ускользнул от основной проблемы - вам нужно как-то различать исходные значения и добавленные вами значения, иначе l oop будет работать бесконечно (или, по крайней мере, до тех пор, пока значения не будут достаточно переполнены) поэтому они начинают повторяться).

Лучший способ сделать это - действительно иметь вспомогательный набор для хранения всех значений, которые вы хотите добавить:

Set<Integer> aux = original.stream().map(i -> i + 7).collect(Collectors.toSet());
original.addAll(aux);
1 голос
/ 14 марта 2020

Если вы не хотите делать копию самостоятельно, Java может сделать это для вас: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArraySet.html. Это не будет быстрее или чем-то волшебным, но вы можете повторить «оригинал» и изменить одновременно.

Однако, если вы хотите что-то более эффективное, то, вероятно, создайте еще один Set с новыми элементами и addAll() их в конце. В зависимости от размера набора может быть быстрее пропустить проверку сдерживания и оставить ее для слияния.

BitSet и ее операция or() также может быть чем-то посмотреть, если ваши числа неотрицательны и имеют низкую величину.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...