Skip to content

Instantly share code, notes, and snippets.

@Taskeren
Created February 1, 2021 09:19
Show Gist options
  • Select an option

  • Save Taskeren/1db8fd362c81dcda92c985dd5ce4d5e8 to your computer and use it in GitHub Desktop.

Select an option

Save Taskeren/1db8fd362c81dcda92c985dd5ce4d5e8 to your computer and use it in GitHub Desktop.
加权随机数 Weighted Random
package testified;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
public class WeightRandom<V> {
private final Random rand;
/** 元素池,随机出来指针后从这里提取元素 */
private final List<V> pool = Lists.newArrayList();
/** 加权最大值 */
private int cap = 0;
/** 加权元素池(元素指针,元素加权值) */
private final Map<Integer, Integer> caps = Maps.newHashMap();
public WeightRandom() {
this(new Random());
}
public WeightRandom(Random rand) {
this.rand = rand;
}
public void add(int weight, V element) {
pool.add(element); // 放到元素池里
caps.put(pool.size()-1, cap+weight); // 放到加权元素池里
cap += weight; // 更新最大加权值
}
public V next() {
final int rind = rand.nextInt(cap); // 随机一个加权值
for(Entry<Integer, Integer> entry : caps.entrySet()) { // 找到刚好比随机加权值小的元素指针
final int ind = entry.getKey();
final int cap = entry.getValue();
if(cap > rind) {
return pool.get(ind);
}
}
throw new IllegalStateException("unexpected");
}
public String toString() {
StringBuilder sb = new StringBuilder("WeightRandom{ ");
caps.forEach( (index, cap) -> {
final V content = pool.get(index);
sb.append(String.valueOf(content)).append("=").append(cap).append(" ");
});
sb.append("}");
return sb.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment