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