Picking a random element from a set Picking a random element from a set java java

Picking a random element from a set


int size = myHashSet.size();int item = new Random().nextInt(size); // In real life, the Random object should be rather more shared than thisint i = 0;for(Object obj : myhashSet){    if (i == item)        return obj;    i++;}


Fast solution for Java using an ArrayList and a HashMap: [element -> index].

Motivation: I needed a set of items with RandomAccess properties, especially to pick a random item from the set (see pollRandom method). Random navigation in a binary tree is not accurate: trees are not perfectly balanced, which would not lead to a uniform distribution.

public class RandomSet<E> extends AbstractSet<E> {    List<E> dta = new ArrayList<E>();    Map<E, Integer> idx = new HashMap<E, Integer>();    public RandomSet() {    }    public RandomSet(Collection<E> items) {        for (E item : items) {            idx.put(item, dta.size());            dta.add(item);        }    }    @Override    public boolean add(E item) {        if (idx.containsKey(item)) {            return false;        }        idx.put(item, dta.size());        dta.add(item);        return true;    }    /**     * Override element at position <code>id</code> with last element.     * @param id     */    public E removeAt(int id) {        if (id >= dta.size()) {            return null;        }        E res = dta.get(id);        idx.remove(res);        E last = dta.remove(dta.size() - 1);        // skip filling the hole if last is removed        if (id < dta.size()) {            idx.put(last, id);            dta.set(id, last);        }        return res;    }    @Override    public boolean remove(Object item) {        @SuppressWarnings(value = "element-type-mismatch")        Integer id = idx.get(item);        if (id == null) {            return false;        }        removeAt(id);        return true;    }    public E get(int i) {        return dta.get(i);    }    public E pollRandom(Random rnd) {        if (dta.isEmpty()) {            return null;        }        int id = rnd.nextInt(dta.size());        return removeAt(id);    }    @Override    public int size() {        return dta.size();    }    @Override    public Iterator<E> iterator() {        return dta.iterator();    }}