├── .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 | --------------------------------------------------------------------------------