Java实现抽奖的两种方式

方式一:随机数在哪个区间内返回区间下标

方式二:随机数加入区间点集合排序返回随机数下标

代码示例:

①抽奖入参类型为BigDecimal:

package com.cfay;import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;/*** @Author lcb* @Date 2022/11/10**/
public class LuckDrawDemo {public static void main(String[] args) {List<BigDecimal> drawList = Lists.newArrayList();drawList.add(BigDecimal.valueOf(0.15));drawList.add(BigDecimal.valueOf(0.3));drawList.add(BigDecimal.valueOf(0.4));//抽奖测试List<Integer> luckDraws = Lists.newArrayList();for (int j = 0; j < 1000000; j++) {luckDraws.add(checkLuckDraw(drawList));}//按照数字进行分组排序Map<Integer, List<Integer>> luckDrawMap = luckDraws.stream().collect(Collectors.groupingBy(Integer::intValue));//遍历打印测试结果luckDrawMap.forEach((key, value) -> System.out.printf("第%s个出现的次数为:%d%n", key, value.size()));}/*** 抽奖检查** @param drawList 抽奖列表* @return 抽中奖品下标*/private static int checkLuckDraw(List<BigDecimal> drawList) {if (CollectionUtils.isEmpty(drawList)) {throw new RuntimeException("抽奖异常!");}if (CollectionUtils.isNotEmpty(drawList.stream().filter(Objects::isNull).collect(Collectors.toList()))) {throw new RuntimeException("抽奖异常!");}return luckDrawArea1(drawList);}/*** 抽奖1** @param drawList 抽奖列表* @return 抽中奖品下标*/private static int luckDrawArea1(List<BigDecimal> drawList) {//所有得到概率之和BigDecimal probability = drawList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);//多个抽奖区间List<List<BigDecimal>> draws = new ArrayList<>(drawList.size());BigDecimal initDraw = BigDecimal.ZERO;//抽奖区间List<BigDecimal> luckDraws;for (BigDecimal draw : drawList) {luckDraws = new ArrayList<>(2);//区间起点luckDraws.add(initDraw);//区间终点initDraw = initDraw.add(draw.divide(probability, 10, BigDecimal.ROUND_HALF_UP));luckDraws.add(initDraw);draws.add(luckDraws);}BigDecimal random = BigDecimal.valueOf(Math.random());//过滤出抽奖区间的位置return draws.indexOf(draws.stream().filter(draw ->draw.get(0).compareTo(random) <= 0 && draw.get(1).compareTo(random) > 0).findAny().orElseGet(ArrayList::new)) + 1;}/*** 抽奖2** @param drawList 抽奖列表* @return 抽中奖品下标*/private static int luckDrawArea2(List<BigDecimal> drawList) {//所有得到概率之和BigDecimal probability = drawList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);//多个抽奖点List<BigDecimal> draws = new ArrayList<>(drawList.size() + 1);//抽奖点BigDecimal initDraws = BigDecimal.ZERO;for (BigDecimal draw : drawList) {initDraws = initDraws.add(draw.divide(probability, 10, BigDecimal.ROUND_HALF_UP));draws.add(initDraws);}//放入随机抽奖区间,并返回抽检区间的下标BigDecimal random = BigDecimal.valueOf(Math.random());draws.add(random);Collections.sort(draws);return draws.indexOf(random) + 1;}
}

②、抽奖入参类型为Double

package com.cfay;import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;import java.util.*;
import java.util.stream.Collectors;/*** @Author lcb* @Date 2022/11/10**/
public class LuckDrawDemo2 {public static void main(String[] args) {List<Double> drawList = Lists.newArrayList();drawList.add(0.15d);drawList.add(0.3d);drawList.add(0.4d);//抽奖测试List<Integer> luckDraws = Lists.newArrayList();for (int j = 0; j < 1000000; j++) {luckDraws.add(checkLuckDraw(drawList));}//按照数字进行分组排序Map<Integer, List<Integer>> luckDrawMap = luckDraws.stream().collect(Collectors.groupingBy(Integer::intValue));//遍历打印测试结果luckDrawMap.forEach((key, value) -> System.out.printf("第%s个出现的次数为:%d%n", key, value.size()));}/*** 抽奖检查** @param drawList 抽奖列表* @return 抽中奖品下标*/private static int checkLuckDraw(List<Double> drawList) {if (CollectionUtils.isEmpty(drawList)) {throw new RuntimeException("抽奖异常!");}if (CollectionUtils.isNotEmpty(drawList.stream().filter(Objects::isNull).collect(Collectors.toList()))) {throw new RuntimeException("抽奖异常!");}if (drawList.stream().reduce(Double::sum).orElse(0d) == 0d) {throw new RuntimeException("抽奖异常!");}return luckDrawArea2(drawList);}/*** 抽奖1** @param drawList 抽奖列表* @return 抽中奖品下标*/private static int luckDrawArea1(List<Double> drawList) {//所有得到概率之和Double probability = drawList.stream().reduce(Double::sum).orElse(0d);//多个抽奖区间List<List<Double>> draws = new ArrayList<>(drawList.size());double initDraw = 0d;//抽奖区间List<Double> luckDraws;for (Double draw : drawList) {luckDraws = new ArrayList<>(2);//区间起点luckDraws.add(initDraw);//区间终点luckDraws.add(initDraw += draw / probability);draws.add(luckDraws);}Double random = Math.random();//过滤出抽奖区间的位置return draws.indexOf(draws.stream().filter(draw ->draw.get(0).compareTo(random) <= 0 && draw.get(1).compareTo(random) > 0).findAny().orElseGet(ArrayList::new)) + 1;}/*** 抽奖2** @param drawList 抽奖列表* @return 抽中奖品下标*/private static int luckDrawArea2(List<Double> drawList) {//所有得到概率之和Double probability = drawList.stream().reduce(Double::sum).orElse(0d);//多个抽奖点List<Double> draws = new ArrayList<>(drawList.size() + 1);//抽奖点double initDraws = 0d;for (Double draw : drawList) {draws.add(initDraws += draw / probability);}//放入随机抽奖区间,并返回抽检区间的下标Double random = Math.random();draws.add(random);Collections.sort(draws);return draws.indexOf(random) + 1;}
}

Java 实现抽奖的两种方式相关推荐

  1. 创建和应用Java包文件的两种方式(转)

    创建和应用Java包文件的两种方式(转) <Java编程艺术>章节选登.作者:高永强 清华大学出版社 (即将出版) 12.1  包--package    ... 12.1.1  包命名规 ...

  2. java制作oracle程序,Java程序操作Oracle两种方式之简单实现

    Java程序操作Oracle两种方式之简单实现 1.通过JDBC-ODBC桥连接Oracle数据库 (1)创建odbc源,在控制面板->管理工具->数据源(odbc)中添加DSN,比如取名 ...

  3. Java格式化倒计时的两种方式

    Java格式化倒计时的两种方式 第一种方式 /*** 入参是一个每秒减小1的秒数* 返回一个格式化的时间* * 该方法具有局限性,他在时间大于1个小时的时候,会返回错误的时间* 因为该方法调用了Dat ...

  4. java操作Excel有两种方式 方式1:jxl操作Excel jxl的API

    java操作Excel有两种方式 方式1:jxl操作Excel 方式2:poi操作Excel 下面介绍jxl API: 使用Windows操作系统的朋友对Excel(电子表格)一定不会陌生,但是要使用 ...

  5. java 产生随机数的两种方式,Java产生随机数的两种方式

    Java产生随机数的两种方式 Java产生随机数的两种方式 在java中,我们可以通过两种方式来获取随机数(generating a random number)一种是大家熟悉的java.lang.M ...

  6. Java读取证书的两种方式

    关于证书基础以及创建.查看.删除.导入.导出以及其他功能详解请参照:Java使用keytool创建CA证书 Java读取证书有两种方式 1.从文件中读取 public static void main ...

  7. 创建和应用Java包文件的两种方式

    <Java编程艺术>章节选登.作者:高永强 清华大学出版社 (即将出版) 12.1  包--package       包是Java提供的文件管理机制.包把功能相似的类,按照Java的名字 ...

  8. java文件读写的两种方式

    今天搞了下java文件的读写,自己也总结了一下,但是不全,只有两种方式,先直接看代码: public static void main(String[] args) throws IOExceptio ...

  9. [Java] HashMap遍历的两种方式

    Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: Map map = new HashMap ...

最新文章

  1. Linux快速入门打开你的学习之道
  2. 『无聊透顶』一篇很无聊的文章
  3. python查看网络连接_python – 检查网络连接
  4. 用python写聊天机器人_用Python 写一个机器人陪你聊天(文尾有彩蛋)
  5. (持续更新)C语言笔试题整理
  6. PLC控制电机正反转原理图
  7. Windows电脑桌面云便签快捷键怎么查看?
  8. 【比赛回顾】广工大2020级年ACM第一次月赛——Dio的面包工坊
  9. 【CVPR 2021】Refine Myself by Teaching Myself : Feature Refinement via Self-Knowledge Distillation
  10. pandas删除包含特定字符串所在的行
  11. 【Office】解决Excel关闭Personal工作簿导致宏不见的情况
  12. 计算机报名怎么老是密码错误,中考报名显示密码错误 中考网上报名说我密码错误怎么办...
  13. Python实现图像去噪(中值去噪和均值去噪)
  14. ubuntu如何连接显示器
  15. Android声卡的工作原理,夏昆冈作品 - 自由的音频,把手机变成无线声卡 SoundWire 应用教程与体会[Soomal]...
  16. C# 屏幕取词 鼠标取词 非剪切板模式
  17. 机器学习和深度学习的三点关键区别
  18. mysql是怎样工作的_六星教育揭秘一个真实的MySQL,述说它能给工作带来怎样的便利?...
  19. 工行发验证码android登陆,工行手机安卓客户端工银钱包问题
  20. 五金配件行业ERP解决方案

热门文章

  1. 把服务器sql数据库导出excel文件,将mysql数据库数据以Excel文件的形式导出
  2. 北京世纪安图在汉参加地理国情监测技术与应用研讨会
  3. 为什么开发与测试老掐架呢
  4. 快排 找第k大的数字
  5. Python 获取动漫番剧 -XXOO
  6. 黑视素照度(EML) Equivalent Melanopic Lux 计算工具
  7. TBase数据库开源后重磅升级,复杂查询性能最高提升十倍
  8. mahout实现协同过滤推荐算法
  9. js把汉字转换成拼音
  10. Revit二次开发入门捷径_升维学习、降维打击