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;
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()));
}
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);
}
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;
}
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;
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()));
}
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);
}
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;
}
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;
}
}