在做一个银行的网页游戏的时候,涉及到一个随机抽奖的模块。具体的需求是:当用户的积分可以抽奖的时候,点击抽奖则消耗指定的积分随机抽取奖品,各种奖品的概率如下:笔记本(10%),手机(20%),充值卡(30%),积分(40%)。因为,奖品的概率是可以设置的,因此考虑Java容器中的TreeMap集合实现该算法。
核心逻辑:

累加每个物品的权重笔记本(10%)-手机(30%)-充值卡(60%)-积分(100%),则4个物品的的权重有效长度区间分别为(0,10]、(10,30]、(30,60]、(60,100]。然后随机出一个[0,10)之间的随机数。落在哪个区间,则该区间之后的元素即为按权重命中的元素。

为什么用TreeMap?

因为TreeMap底层用红黑树实现,TreeMap中的key是唯一且有序的,因此TreeMap提供了如下方法:

NavigableMap<K,V>  tailMap(K fromKey, boolean inclusive) 返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。K lastKey() 返回映射中当前最后一个(最高)键。K  firstKey() 返回此映射中当前第一个(最低)键。

试想,当我们用普通的不可动态扩展的方法如if/switch方法实现时,必然是产生一个随机数,然后判断该随机数在哪个概率区间。TreeMap因为有序,因此刚好提供了两个方法tailMap,firstKey用于实现落点区间判断的逻辑,简洁又高效,并且方便动态扩展。
具体的代码实现:

package icerno.com.weightRandom;import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;import org.apache.commons.math3.util.Pair;import com.cookingfox.guava_preconditions.Preconditions;public class WeightRandom<K,V extends Number> {private TreeMap<Double, K> weightMap = new TreeMap<Double, K>();public WeightRandom(List<Pair<K, V>> list) {Preconditions.checkNotNull(list, "list can NOT be null!");for (Pair<K, V> pair : list) {double lastWeight = this.weightMap.size() == 0 ? 0 : this.weightMap.lastKey().doubleValue();//统一转为doublethis.weightMap.put(pair.getValue().doubleValue() + lastWeight, pair.getKey());//权重累加}System.out.println("------Tree init OK!--------");}public K random() {double randomWeight = this.weightMap.lastKey() * Math.random();SortedMap<Double, K> tailMap = this.weightMap.tailMap(randomWeight, true);return this.weightMap.get(tailMap.firstKey());}@SuppressWarnings({ "rawtypes", "unchecked" })public static void main(String[] args){List<Pair<String,Double>> list = new ArrayList<Pair<String,Double>>();list.add(new Pair<String,Double>("A",0.20));list.add(new Pair<String,Double>("C",0.50));list.add(new Pair<String,Double>("B",0.30));WeightRandom weightRandom = new WeightRandom(list);Object random = weightRandom.random();System.out.println("----Key----"+random);}
}

注意:TreeMap为异步的非线程安全的,因此在并发要求高时,可以使用如下代码加锁。

public static Map<Double, K> treemap = Collections.synchronizedMap(new TreeMap<Double, K>());

参考文章:
权重随机算法的java实现
Java TreeMap 介绍和使用

带权重的随机数算法的实现相关推荐

  1. 【酷熊科技】工作积累 ----------- 随机数 (带权重的随机数)

    依靠权重来随机 思路 : 先 随机 每个 随机段 权重 然后 通过 随机出来 的权重 判断在 哪个 随机段 内 然后再在这个 随机段 中 随机出来 需要 的随机数 举例: 需求: 50 ~ 999 随 ...

  2. python概率随机抽奖_Python利用带权重随机数解决抽奖和游戏爆装备

    关于带权随机数 为了帮助理解,先来看三类随机问题的对比: 1.已有n条记录,从中选取m条记录,选取出来的记录前后顺序不管. 实现思路:按行遍历所有记录,约隔n/m条取一个数据即可 2.在1类情况下,还 ...

  3. 关于寻路算法的一些思考(3):A*算法的实现

    概述 剥除代码,A* 算法非常简单.算法维护两个集合:OPEN 集和 CLOSED 集.OPEN 集包含待检测节点.初始状态,OPEN集仅包含一个元素:开始位置.CLOSED集包含已检测节点.初始状态 ...

  4. 计算机LCG/PCG/MWC/XorShift等PRNG算法,以及V8中Math.random()、webkit中crypto等随机算法的实现

    计算机LCG/PCG/MWC/XorShift等PRNG算法,以及V8中Math.random().webkit中crypto等随机算法的实现 本文篇幅较长,如想直接看 js 的随机数实现可定位本文E ...

  5. 传授“带权重的负载均衡实现算法”独家设计思路!

    作者|孙玄/陈东 分布式系统中,大部分系统调用都会涉及到负载均衡,例如:客户端发往服务端的请求首先到达反向代理,然后反向代理再通过负载均衡算法将请求转发到业务系统:或者后端业务系统各模块间的调用前,也 ...

  6. 干货回顾丨TensorFlow四种Cross Entropy算法的实现和应用

    交叉熵介绍 交叉熵(Cross Entropy)是Loss函数的一种(也称为损失函数或代价函数),用于描述模型预测值与真实值的差距大小,常见的Loss函数就是均方平方差(Mean Squared Er ...

  7. 选择性模糊及其算法的实现。

    选择性模糊及其算法的实现. 我们常见的模糊算法比如均值模糊.高斯模糊等其基本的过程都是计算一个像素周边的的某个领域内,相关像素的某个特征值的累加和及对应的权重,然后得到结果值.比如均值模糊的各像素的权 ...

  8. RSA算法和RSA数字签名算法的实现

    RSA算法和RSA数字签名算法的实现 http://blog.chinaunix.net/uid-21880738-id-1813146.html 顾婷婷 李涛 (四川大学计算机系(西区) 成都 61 ...

  9. 游戏中常用的寻路算法的分享(3):A*算法的实现

    概述 剥除代码,A* 算法非常简单.算法维护两个集合:OPEN 集和 CLOSED 集.OPEN 集包含待检测节点.初始状态,OPEN集仅包含一个元素:开始位置.CLOSED集包含已检测节点.初始状态 ...

最新文章

  1. 宜家通信- 会员管理 表结构搭建
  2. IIS弹出服务没有及时响应启动或控制请求
  3. 拉勾网《32个Java面试必考点》学习笔记之二------操作系统与网络知识
  4. 思考--为何早晨型人更容易成功
  5. windows下的文本文件在linux下查看,中文显示乱码
  6. linux tomcat 启动权限不足解决办法
  7. OnKeyPress事件和Javascript检测键盘输入
  8. 关于安装完Node.js 出现node is not dedined 问题
  9. 惠普招聘 运维质量管理顾问 1名 北京
  10. 这台计算机上缺少此项目引用的 NuGet 程序包,DotNetCompilerPlatform
  11. mysql connector 是什么_mysql的connector/J,和JDBC是啥关系?有啥区别?
  12. python代码风格
  13. 小学 学生学籍信息汇总及自动检查代码(Python)
  14. 【原创】CSS3动画总结对比 / 带思维导图 / 启发小案例
  15. 个人简历模板(网页版)
  16. 上传文件框在firefox浏览器中显示路径不全的解决方法
  17. 大数据分析笔记 (2) - 数据分析统计方法
  18. 程序员也要学英语——名词和代词
  19. CodeForces - 863B-Kayaking(暴力)
  20. [聊天机器人]:开源ChatterBot工作原理

热门文章

  1. Michael S. Hart去世了
  2. 【聆思CSK6视觉AI开发套件试用】基于AI手势识别的剪子包袱锤游戏
  3. 学习札记————问题札记
  4. 游戏陪玩APP开发的功能和特点
  5. 首页 个人简历,个人主页,个人介
  6. 主编编辑器如何新建文章?
  7. 黑苹果cpu支持列表_单卡gpu直通,黑苹果,amd_cpu教程
  8. c语言--数组求平均数并且输出大于平均数的数
  9. ensp关于MPLS的实验
  10. 最新「深度学习社区发现」综述论文,174篇文献概述六大类方法(含Github资源)...