Some areas of my Java grow rusty with time, as with all things. This code looks nice, but completely fails:
public static void main(final String... args) {
final Set<Foo> foos = new HashSet<Foo>(asList(FOO));
for (final Foo foo : foos)
foos.addAll(foo.more);
System.out.println("foos = " + new HashSet<Foo>(foos));
}
enum Foo {
QUUX,
BAZ(QUUX),
BAR(BAZ),
FOO(BAR, BAZ);
private final Set<Foo> more;
Foo(final Foo... more) {
this.more = new HashSet<Foo>(asList(more));
}
} The goal is to collect all transitive dependencies. What is wrong?
The iterator is not a "current picture" of the collection; it is a snapshot. This code prints only foos = [FOO], updates vanish. Changing to ArrayList only worsens things with the dreaded ConcurrentModificationException.
Correct is to use a list iterator and be careful with cursor position:
public static void main(final String... args) {
final List<Foo> foos = new ArrayList<Foo>(asList(FOO));
final ListIterator<Foo> lit = foos.listIterator();
while (lit.hasNext())
for (final Foo foo : lit.next().more) {
lit.add(foo);
lit.previous();
}
System.out.println("foos = " + new HashSet<Foo>(foos));
} This prints foos = [QUUX, BAZ, BAR, FOO] with the happy side effect of depth-first ordering.
No comments:
Post a Comment