I have no reputation for a comment on @PeterLawrey's
answer:Random weighted selection in Java. It is good. But now I call next()
get a result as A and want to remove weight for A from map
to avoid to get A again. How can I deal with it?
Asked
Active
Viewed 787 times
1

Bhargav Rao
- 50,140
- 28
- 121
- 140

kinglao
- 151
- 9
1 Answers
0
You can simply change this line, in PeterLawrey's solution
public E next() {
double value = random.nextDouble() * total;
return map.higherEntry(value).getValue();
}
to
public E next() {
double value = random.nextDouble() * total--;
return map.remove(higherKey(value));
}
cause remove()
returns the associated value after removing
Alternatively, if you need to remove elements after choosing you can use another solution. Add all the elements into a 'LinkedList', each element must be added as many times as it weight is, then use Collections.shuffle()
which, according to JavaDoc
Randomly permutes the specified list using a default source of randomness. All permutations occur with approximately equal likelihood.
Finally, get and remove elements using pop()
or removeFirst()
Map<String, Integer> map = new HashMap<String, Integer>() {{
put("Five", 5);
put("Four", 4);
put("Three", 3);
put("Two", 2);
put("One", 1);
}};
LinkedList<String> list = new LinkedList<>();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
for (int i = 0; i < entry.getValue(); i++) {
list.add(entry.getKey());
}
}
Collections.shuffle(list);
System.out.println("Size: " + list.size());
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.pop());
}
System.out.println("Size: " + list.size());

Yuri H
- 680
- 5
- 12
-
@kinglao Was my answer helpful? Could you choose it as the correct one? – Yuri H Jun 06 '17 at 12:38
-
I think just remove can not work. Because the `total` field should change too – kinglao Jun 07 '17 at 02:11
-
@kinglao Definitely, it should be changed too according to program logic. Maybe, the second solution will be more suitable for your purposes. – Yuri H Jun 07 '17 at 07:45