/** * 根据权重,随机取出值 * @param dataWeightMap 数据-权重 的映射 * @param <T> 数据类型 * @return 根据权重随机的数据 */ public static <T> T randomWeight(Map<T, Integer> dataWeightMap){ // <数据, int[min, max]> 计算是否属于此范围时:前包后不包 Map<T, int[]> rangeMapper = new HashMap<>(); int count=0; for(T data : dataWeightMap.keySet()){ // 初始化权重 Integer weight = dataWeightMap.get(data); weight = weight == null ? 1 : weight; if(weight < 1) { continue; } // 初始化范围 int[] range = new int[2]; rangeMapper.put(data, range); // 计算随机范围 range[0] = count; count += weight; range[1] = count; } // 生成随机数,并判断符合权重范围(前包后不包)的数据 int randNum = (int) (Math.random() * count); for(T data : rangeMapper.keySet()){ int[] range = rangeMapper.get(data); if(randNum >= range[0] && randNum < range[1]) { return data; } } return null; }
测试:
/**
* 权重随机返回测试
* @param args
*/
public static void main(String[] args) {
Map<String, Integer> dataWeightMap = new HashMap<>();
dataWeightMap.put("A", 2);
dataWeightMap.put("B", 1);
dataWeightMap.put("C", 2);
dataWeightMap.put("D", 1);
Map<String, Integer> countMap = new HashMap<>();
dataWeightMap.forEach((k, v) -> countMap.put(k, 0));
int num = 1000000;
for(int i=0; i< num; i ++) {
String res = randomWeight(dataWeightMap);
countMap.compute(res, (k, v) -> v + 1);
}
countMap.forEach((k, v) -> System.out.println(k+":"+v));
}
结果:
A:332530
B:166882
C:333462
D:167126
====================
A:332845
B:167135
C:333458
D:166562
可自行修改参数,反复测试
标签:weight,权重,int,data,range,随机,dataWeightMap,put,数据 From: https://www.cnblogs.com/ryuusho/p/17529385.html