本文目录导读:

在Java中分配不同场景的权重,常见的有以下几种方法,我根据实际需求逐一说明:
简单权重分配(比例分配)
适用于按固定比例分配,比如抽奖、A/B测试。
import java.util.Random;
public class WeightedRandom {
// 场景枚举
enum Scenario {
SCENARIO_A(0.5), // 50%概率
SCENARIO_B(0.3), // 30%概率
SCENARIO_C(0.2); // 20%概率
private final double weight;
Scenario(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
}
public static Scenario getRandomScenario() {
double random = Math.random();
double cumulativeWeight = 0;
for (Scenario scenario : Scenario.values()) {
cumulativeWeight += scenario.getWeight();
if (random < cumulativeWeight) {
return scenario;
}
}
return Scenario.values()[0]; // 兜底
}
public static void main(String[] args) {
// 测试10000次
int countA = 0, countB = 0, countC = 0;
for (int i = 0; i < 10000; i++) {
switch (getRandomScenario()) {
case SCENARIO_A: countA++; break;
case SCENARIO_B: countB++; break;
case SCENARIO_C: countC++; break;
}
}
System.out.printf("A: %.2f%%, B: %.2f%%, C: %.2f%%%n",
countA/100.0, countB/100.0, countC/100.0);
}
}
基于配置文件的权重管理
适合需要动态调整权重的场景。
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class ConfigurableWeight {
private Map<String, Double> weights = new HashMap<>();
// 从配置加载权重
public void loadWeights(Properties config) {
config.stringPropertyNames().forEach(key -> {
if (key.startsWith("scenario.")) {
String scenario = key.substring("scenario.".length());
double weight = Double.parseDouble(config.getProperty(key));
weights.put(scenario, weight);
}
});
}
public String getScenarioByWeight() {
double random = Math.random();
double cumulative = 0;
// 按权重排序后选择
for (Map.Entry<String, Double> entry : weights.entrySet()) {
cumulative += entry.getValue();
if (random < cumulative) {
return entry.getKey();
}
}
return null;
}
public static void main(String[] args) {
// 模拟配置
Properties config = new Properties();
config.setProperty("scenario.new_user", "0.3");
config.setProperty("scenario.vip_user", "0.5");
config.setProperty("scenario.normal_user", "0.2");
ConfigurableWeight weightManager = new ConfigurableWeight();
weightManager.loadWeights(config);
// 获取场景
System.out.println("选中场景: " + weightManager.getScenarioByWeight());
}
}
基于权重的影响因子模型
适用于推荐系统、业务决策等复杂场景。
import java.util.HashMap;
import java.util.Map;
public class WeightFactorModel {
// 场景权重因子
private static class Factor {
double baseWeight; // 基础权重
Map<String, Double> ifFactors; // 条件因子
Factor(double baseWeight) {
this.baseWeight = baseWeight;
this.ifFactors = new HashMap<>();
}
void addFactor(String condition, double weight) {
ifFactors.put(condition, weight);
}
double calculateWeight(String... conditions) {
double totalWeight = baseWeight;
for (String condition : conditions) {
if (ifFactors.containsKey(condition)) {
totalWeight *= ifFactors.get(condition);
}
}
return totalWeight;
}
}
public static void main(String[] args) {
Map<String, Factor> scenarioFactors = new HashMap<>();
// 定义场景A及其因子
Factor factorA = new Factor(1.0);
factorA.addFactor("user_is_new", 1.5); // 新用户权重加倍
factorA.addFactor("user_is_mobile", 1.2); // 移动端增加权重
scenarioFactors.put("scenario_A", factorA);
// 定义场景B
Factor factorB = new Factor(0.8);
factorB.addFactor("user_is_vip", 2.0); // VIP用户权重加倍
scenarioFactors.put("scenario_B", factorB);
// 实际使用
String userType = "user_is_vip";
boolean isMobile = false;
for (Map.Entry<String, Factor> entry : scenarioFactors.entrySet()) {
String scenario = entry.getKey();
Factor factor = entry.getValue();
double weight = factor.calculateWeight(userType);
System.out.printf("场景: %s, 计算权重: %.2f%n", scenario, weight);
}
}
}
动态权重调整(基于用户行为)
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DynamicWeightAdjuster {
// 用户ID -> 场景权重映射
private Map<String, Map<String, Double>> userScenarioWeights = new ConcurrentHashMap<>();
// 初始化默认权重
private static final Map<String, Double> DEFAULT_WEIGHTS = new HashMap<>() {{
put("detail_page", 0.6); // 详情页
put("comment_page", 0.3); // 评论页
put("recommend_page", 0.1); // 推荐页
}};
// 记录用户行为并调整权重
public void recordBehavior(String userId, String scenario, int times) {
Map<String, Double> userWeights =
userScenarioWeights.computeIfAbsent(userId, k -> new HashMap<>(DEFAULT_WEIGHTS));
// 根据行为次数调整权重
userWeights.computeIfPresent(scenario, (key, weight) ->
weight * (1 + times * 0.1)); // 每次行为增加10%权重
}
// 获取用户场景权重
public String getNextScenario(String userId) {
Map<String, Double> weights =
userScenarioWeights.getOrDefault(userId, DEFAULT_WEIGHTS);
// 权重归一化并随机选择
double total = weights.values().stream().mapToDouble(Double::doubleValue).sum();
double random = Math.random() * total;
double cumulative = 0;
for (Map.Entry<String, Double> entry : weights.entrySet()) {
cumulative += entry.getValue();
if (random < cumulative) {
return entry.getKey();
}
}
return "detail_page"; // 默认
}
}
实用建议
选择权重分配方案时考虑:
- 固定比例:简单场景用轮询/随机
- 可配置:需要运营调整用配置文件
- 动态计算:考虑多种因素用因子模型
- 个性化:需要用户差异化用动态调整
性能优化提示:
// 预计算累积权重,避免每次循环
private static final NavigableMap<Double, Scenario> WEIGHT_MAP =
new TreeMap<>();
static {
double cumulative = 0;
for (Scenario s : Scenario.values()) {
cumulative += s.getWeight();
WEIGHT_MAP.put(cumulative, s);
}
}
public static Scenario getFastRandom() {
double random = Math.random() * WEIGHT_MAP.lastKey();
return WEIGHT_MAP.higherEntry(random).getValue();
}
根据具体业务选择合适的方案,保持代码简洁和可维护性。