java - How can I randomize the iteration sequence of a Set? -
i need use set collection.
each time start jvm run program, want iterate through items in set in randomly decided sequence.
the iteration sequence has nothing sequence in placed them in set, right?
so, do? how can randomize iteration sequence in set?
here method, , not randomize.
public static <t> void shuffle(set<t> set) { list<t> shuffleme = new arraylist<t>(set); collections.shuffle(shuffleme); set.clear(); set.addall(shuffleme); }
what need randomizingiterator
set unordered, randomizing unordered collection doesn't make logical sense.
an ordered set ordered using comparator means has fixed order, can't shuffle it, has no meaning order determined comparator or compare() method.
set -> list allow shuffle contents of list , use custom randomizingiterator iterate across set.
example implementation :
link gist on github - testrandomizingiterator.java
import org.junit.test; import javax.annotation.nonnull; import java.util.*; public class testrandomzingiterator { @test public void testrandomiteration() { final set<string> set = new hashset<string>() { /** every call iterator() give possibly unique iteration order, or not */ @nonnull @override public iterator<string> iterator() { return new randomizingiterator<string>(super.iterator()); } class randomizingiterator<t> implements iterator<t> { final iterator<t> iterator; private randomizingiterator(@nonnull final iterator<t> iterator) { list<t> list = new arraylist<t>(); while(iterator.hasnext()) { list.add(iterator.next()); } collections.shuffle(list); this.iterator = list.iterator(); } @override public boolean hasnext() { return this.iterator.hasnext(); } @override public t next() { return this.iterator.next(); } /** * modifying makes no logical sense, simplicity sake, implementation immutable. * done, added complexity. */ @override public void remove() { throw new unsupportedoperationexception("testrandomzingiterator.randomizingiterator.remove"); } } }; set.addall(arrays.aslist("a", "b", "c")); final iterator<string> iterator = set.iterator(); while (iterator.hasnext()) { system.out.println(iterator.next()); } } } notes:
this straw man example, intention clear, use custom iterator custom iteration.
you can't normal iteration behavior back, doesn't seem problem use case.
passing the super.iterator() facade important, stackoverflowerror otherwise, because becomes recursive call if pass this .addall() or list() constructor.
hashset may appear ordered isn't guaranteed stay ordered, order depends on hashcode of objects , adding single object may reorder how contents order, contract of set interface order undefined , in particular hashset nothing more facade on backing map.keyset().
there other more supposedly light weight, more complex solutions use original iterator , try , keep track of has been seen, solutions aren't improvements on technique unless size of data excessively large, , looking @ on disk structures @ point.
Comments
Post a Comment