本文目录导读:

我来介绍几种常见的Java抽奖算法实现方案。
基础随机抽奖(简单抽奖)
实现方式一:简单随机
import java.util.*;
public class SimpleLottery {
private List<String> participants;
private Random random;
public SimpleLottery(List<String> participants) {
this.participants = new ArrayList<>(participants);
this.random = new Random();
}
// 单次抽奖
public String draw() {
if (participants.isEmpty()) {
return "没有参与者";
}
int index = random.nextInt(participants.size());
return participants.get(index);
}
// 抽取多个获奖者(不重复)
public List<String> drawMultiple(int count) {
List<String> winners = new ArrayList<>();
List<String> tempList = new ArrayList<>(participants);
for (int i = 0; i < count && !tempList.isEmpty(); i++) {
int index = random.nextInt(tempList.size());
winners.add(tempList.remove(index));
}
return winners;
}
}
权重抽奖算法
实现方式二:加权随机
public class WeightedLottery {
private List<Prize> prizes;
private double totalWeight;
private Random random;
public WeightedLottery(List<Prize> prizes) {
this.prizes = prizes;
this.random = new Random();
this.totalWeight = prizes.stream()
.mapToDouble(Prize::getWeight)
.sum();
}
// 根据权重抽奖
public Prize draw() {
double currentWeight = random.nextDouble() * totalWeight;
double cumulativeWeight = 0;
for (Prize prize : prizes) {
cumulativeWeight += prize.getWeight();
if (currentWeight <= cumulativeWeight) {
return prize;
}
}
return prizes.get(prizes.size() - 1);
}
// 奖品类
public static class Prize {
private String name;
private double weight; // 权重值
public Prize(String name, double weight) {
this.name = name;
this.weight = weight;
}
public String getName() { return name; }
public double getWeight() { return weight; }
}
}
完整抽奖系统示例
import java.util.*;
import java.util.stream.Collectors;
public class LotterySystem {
private List<Participant> participants;
private List<Prize> prizes;
private Random random;
private Map<String, Integer> prizeCount; // 奖品库存
public LotterySystem() {
this.participants = new ArrayList<>();
this.prizes = new ArrayList<>();
this.random = new Random();
this.prizeCount = new HashMap<>();
}
// 添加参与者
public void addParticipant(String name, double weight) {
participants.add(new Participant(name, weight));
}
// 添加奖品
public void addPrize(String name, int quantity) {
prizes.add(new Prize(name, quantity));
prizeCount.put(name, quantity);
}
// 执行抽奖
public LotteryResult draw() {
if (participants.isEmpty() || prizes.isEmpty()) {
return new LotteryResult(null, null, "参与者或奖品不足");
}
// 检查剩余奖品
List<Prize> availablePrizes = prizes.stream()
.filter(p -> p.getRemaining() > 0)
.collect(Collectors.toList());
if (availablePrizes.isEmpty()) {
return new LotteryResult(null, null, "奖品已抽完");
}
// 选择获奖者(权重算法)
Participant winner = selectWinner();
// 选择奖品(简单随机)
Prize prize = selectPrize(availablePrizes);
// 更新奖品库存
prize.decrementRemaining();
return new LotteryResult(winner, prize, "恭喜中奖");
}
// 权重选择获奖者
private Participant selectWinner() {
double totalWeight = participants.stream()
.mapToDouble(Participant::getWeight)
.sum();
double targetWeight = random.nextDouble() * totalWeight;
double cumulativeWeight = 0;
for (Participant p : participants) {
cumulativeWeight += p.getWeight();
if (targetWeight <= cumulativeWeight) {
return p;
}
}
return participants.get(participants.size() - 1);
}
// 随机选择奖品
private Prize selectPrize(List<Prize> availablePrizes) {
int index = random.nextInt(availablePrizes.size());
return availablePrizes.get(index);
}
// 内部类
public static class Participant {
private String name;
private double weight;
public Participant(String name, double weight) {
this.name = name;
this.weight = weight;
}
public String getName() { return name; }
public double getWeight() { return weight; }
}
public static class Prize {
private String name;
private int total;
private int remaining;
public Prize(String name, int total) {
this.name = name;
this.total = total;
this.remaining = total;
}
public String getName() { return name; }
public int getRemaining() { return remaining; }
public void decrementRemaining() { this.remaining--; }
}
public static class LotteryResult {
private Participant winner;
private Prize prize;
private String message;
public LotteryResult(Participant winner, Prize prize, String message) {
this.winner = winner;
this.prize = prize;
this.message = message;
}
@Override
public String toString() {
if (winner == null || prize == null) {
return "抽奖结果: " + message;
}
return String.format("恭喜 %s 获得 %s!",
winner.getName(), prize.getName());
}
}
}
使用示例
public class LotteryDemo {
public static void main(String[] args) {
LotterySystem system = new LotterySystem();
// 添加参与者
system.addParticipant("张三", 1.0);
system.addParticipant("李四", 2.0); // 权重更高
system.addParticipant("王五", 1.0);
// 添加奖品
system.addPrize("一等奖", 1);
system.addPrize("二等奖", 2);
system.addPrize("三等奖", 3);
// 执行多次抽奖
for (int i = 0; i < 5; i++) {
LotterySystem.LotteryResult result = system.draw();
System.out.println(result);
}
}
}
进阶:公平洗牌算法
public class FisherYatesShuffle {
// Fisher-Yates洗牌算法,确保公平性
public static <T> void shuffle(List<T> list) {
Random random = new Random();
for (int i = list.size() - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
// 交换元素
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
// 使用洗牌算法抽奖
public static <T> List<T> drawWinners(List<T> participants, int count) {
List<T> shuffled = new ArrayList<>(participants);
shuffle(shuffled);
return shuffled.subList(0, Math.min(count, shuffled.size()));
}
}
- 简单随机:适用于所有参与者概率相同的情况
- 权重算法:适用于不同参与者或奖品有不同中奖概率的场景
- 库存管理:确保奖品不会超发
- 洗牌算法:提供最公平的随机分布
- 线程安全:多线程环境需考虑同步
选择哪种算法取决于你的具体需求:是否需要权重、是否需要库存管理、并发访问要求等。