maplemaple
maplemaple

Reputation: 1725

How to add element to a HashSet while iterating this HashSet?

I have a use case like following:

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

How to implement this using Java HashSet except using an auxiliary list/set to store the element which needs to be inserted?

Upvotes: 2

Views: 2054

Answers (3)

tquadrat
tquadrat

Reputation: 4054

It is impossible to add something to the Set instance while iterating over its contents; when using the foreach loop (for( var e : set ) notation), no modification is allowed, while when using an explicit iterator (for( var i = set.iterator(); i.hasNext(); ) … notation), you can call i.remove() to get rid of the current element. But adding new elements does still not work in this case.

This behaviour is shared by all Java Collection classes, although List knows a special iterator class, ListIterator, that also allows adding entries (notation for( var i = list.listIterator(); i.hasNext(); ) …) by calling i.add() – thanks to @lucasvw for reminding me on that.

Upvotes: 4

tevemadar
tevemadar

Reputation: 13225

If you do not want to make a copy yourself, Java can do that for you: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArraySet.html. It will not be faster or anything magical, but you can iterate "the original" and modify at the same time.

However if you want something efficient, that is presumably to create another Set with the new elements, and addAll() them at the end. Depending on the size of the set it may be faster to skip the containment-check, and leave it for the merging.

BitSet and its or() operation may be also something to look at if your numbers are nonnegative and are of low magnitude.

Upvotes: 1

Mureinik
Mureinik

Reputation: 312259

@lucasvw eluded to the underlying issue here - you need to somehow differentiate between the original values and the values you've added, otherwise, the loop will run indefinitely (or, at least, until the values overflow enough so they start repeating themselves).

The best way to do this is to indeed have an auxiliary set to hold all the values you want to add:

Set<Integer> aux = original.stream().map(i -> i + 7).collect(Collectors.toSet());
original.addAll(aux);

Upvotes: 2

Related Questions