├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
└── java
└── net
└── ewant
└── LotteryUtil.java
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /bin/
3 | *.iml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lottery
2 |
3 | 抽奖业务核心工具类
4 |
5 | 电商系统必备工具.
6 |
7 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | net.ewant
5 | lottery
6 | 1.0.0-SNAPSHOT
7 | jar
8 | lottery
9 | http://maven.apache.org
10 |
11 |
12 |
13 |
14 |
15 |
16 | ${basedir}/src/main/resources
17 |
18 | **/*
19 |
20 |
21 |
22 |
23 |
24 | maven-compiler-plugin
25 |
26 | 1.7
27 | 1.7
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/java/net/ewant/LotteryUtil.java:
--------------------------------------------------------------------------------
1 | package net.ewant;
2 |
3 | import java.lang.reflect.Method;
4 | import java.util.ArrayList;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | public class LotteryUtil {
9 |
10 | /**
11 | * 抽奖
12 | * @param prizes
13 | * 任何需要概率计算的对象(T:必须为拥有probability属性的对象或数值型对象)
14 | * @param field
15 | * 具体概率字段名(实体对象默认probability,数值型对象可不传)
16 | * @return
17 | * prizes 列表的中奖index, -1 则表示抽奖失败
18 | */
19 | public static int lottery(List prizes,String... field) {
20 | try {
21 | if (prizes == null || prizes.isEmpty()) {
22 | return -1;
23 | }
24 | int size = prizes.size();
25 | String f = "probability";
26 | T t = prizes.get(0);
27 | boolean isBasicType = false;
28 | if(t instanceof Double || t instanceof Float || t instanceof String){
29 | isBasicType = true;
30 | }else{
31 | if(field != null && field.length > 0){
32 | f = field[0];
33 | }
34 | }
35 | // 计算总概率,这样可以保证不一定总概率是1 (关系到权重的问题)
36 | double sumRate = 0d;
37 | List orignalRates = new ArrayList<>(size);
38 |
39 | for (T gift : prizes) {
40 | double probability = 0;
41 | if (isBasicType) {
42 | probability = Double.parseDouble(gift.toString());
43 | }else{
44 | Method method = gift.getClass().getMethod("get"+f.substring(0, 1).toUpperCase()+f.substring(1));
45 | Object invoke = method.invoke(gift);
46 | if (invoke != null) {
47 | probability = Double.parseDouble(invoke.toString());
48 | }
49 | }
50 | if (probability < 0) {
51 | probability = 0;
52 | }
53 | sumRate += probability;
54 | orignalRates.add(probability);
55 | }
56 |
57 | // 计算每个物品在总概率的基础下的概率情况(构建区间,核心部分)
58 | List sortOrignalRates = new ArrayList<>(size);
59 | Double tempSumRate = 0d;
60 | for (double rate : orignalRates) {
61 | tempSumRate += rate;
62 | sortOrignalRates.add(tempSumRate / sumRate);
63 | }
64 | // 根据区间值来获取抽取到的物品索引,理论上random随机概率是均等的,因此区间的大小决定了概率大小
65 | double nextDouble = Math.random();
66 | sortOrignalRates.add(nextDouble);
67 | Collections.sort(sortOrignalRates);
68 |
69 | return sortOrignalRates.indexOf(nextDouble);
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 | return -1;
74 | }
75 |
76 | static class Gift {
77 | private String name;
78 | private double probability;
79 | private int total;
80 | private int count;
81 |
82 |
83 | public Gift(String name, double probability) {
84 | this.name = name;
85 | this.probability = probability;
86 | }
87 |
88 | public String getName() {
89 | return name;
90 | }
91 |
92 | public void setName(String name) {
93 | this.name = name;
94 | }
95 |
96 | public double getProbability() {
97 | return probability;
98 | }
99 |
100 | public void setProbability(double probability) {
101 | this.probability = probability;
102 | }
103 | }
104 |
105 | public static void main(String[] args) {
106 | List prizes = new ArrayList<>();
107 | prizes.add(new Gift("50金币", 0.06));
108 | prizes.add(new Gift("充气娃娃1个", 0.01));
109 | prizes.add(new Gift("10元话费", 0.03));
110 | prizes.add(new Gift("10金币", 0.1));
111 | prizes.add(new Gift("谢谢惠顾", 0.8));
112 |
113 | int p0 = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0;
114 | long start = System.currentTimeMillis();
115 | int total = 100000;
116 | for (int i = 0; i < total; i++) {
117 | int lottery = lottery(prizes);
118 | if(lottery == 0){
119 | p0++;
120 | }else if(lottery == 1){
121 | p1++;
122 | }else if(lottery == 2){
123 | p2++;
124 | }else if(lottery == 3){
125 | p3++;
126 | }else if(lottery == 4){
127 | p4++;
128 | }
129 | }
130 |
131 | System.out.println(p0 + " 人抽到: " + prizes.get(0).getName());
132 | System.out.println(p1 + " 人抽到: " + prizes.get(1).getName());
133 | System.out.println(p2 + " 人抽到: " + prizes.get(2).getName());
134 | System.out.println(p3 + " 人抽到: " + prizes.get(3).getName());
135 | System.out.println(p4 + " 人抽到: " + prizes.get(4).getName());
136 |
137 | start = System.currentTimeMillis() - start;
138 | System.out.println("参与人数: " + total + ", 耗时: " + start + "ms");
139 | }
140 | }
141 |
--------------------------------------------------------------------------------