Today I ran into some weird behaviour with a HashSet's iterator.
In the code example below, idString
uses an object reference returned by hs.iterator
to call the iterator's next()
method.
In idString2
the iterator is called via hs.iterator()
and it does not work anymore.
So I assume that HashSet.iterator() returns a new iterator object each time it is called. But then, why can I still use hs.iterator().hasNext()
in the while loop?
(Note that the code below is just an example :) )
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import org.junit.Test;
public class DummyTest {
static final HashSet<Integer> TEST_DATA = new HashSet<Integer>(
Arrays.asList(new Integer[] {
1,2,3,4,5,6,7,8,9,10
}));
@Test
public void testRunTest() {
// Correct output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
System.out.println(idString(TEST_DATA));
// Only 1, 1, 1, 1, ...
System.out.println(idString2(TEST_DATA));
}
static String idString(HashSet<Integer> hs) {
Iterator<Integer> it = hs.iterator();
String res = it.next() + "";
while (it.hasNext()) {
res += ", " + it.next();
System.out.println(res); // debug
}
return res;
}
static String idString2(HashSet<Integer> hs) {
Iterator<Integer> it = hs.iterator();
// Prevent an infinite loop
int i = 0;
String res = null;
res = it.next() + "";
while (hs.iterator().hasNext() && i++ <= 10) {
// if replacing hs.iterator() with 'it', it works
res = res + ", " + hs.iterator().next();
System.out.println(res); // debug
}
return res;
}
}
Each time you call iterator()
it returns a new iterator, independent of any other iterators created before. So if you call hs.iterator().next()
that will always give you the first element, and if you call hs.iterator().hasNext()
on a non-empty collection, it will always return true
.
Compare that with using it
each time, which uses a single iterator throughout, therefore advancing the logical "cursor" each time you call next()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With