使用hutool权重随机获取值或对象

文章目录

场景

按照权重给用户分组;比如按照权重20,30,40,10给用户分组为A,B,C,D

实现

内部实现也是基于TreeMap.tailMap的方法,
详见https://blog.51cto.com/javayida/7485758#TreeMaptailMap_4

参考hutool的类:cn.hutool.core.lang.WeightRandom

权重随机算法实现

平时,经常会遇到权重随机算法,从不同权重的N个元素中随机选择一个,并使得总体选择结果是按照权重分布的。如广告投放、负载均衡等。

如有4个元素A、B、C、D,权重分别为1、2、3、4,随机结果中A:B:C:D的比例要为1:2:3:4。

总体思路:累加每个元素的权重A(1)-B(3)-C(6)-D(10),则4个元素的的权重管辖区间分别为[0,1)、[1,3)、[3,6)、[6,10)。 然后随机出一个[0,10)之间的随机数。落在哪个区间,则该区间之后的元素即为按权重命中的元素。

参考博客:https://www.cnblogs.com/waterystone/p/5708063.html

测试main方法

java 复制代码
import cn.hutool.core.lang.WeightRandom;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName RandomTest
 * @Author yida
 * @Date 2023-09-14 18:26
 * @Description RandomTest
 */
public class RandomTest {

    public static void main(String[] args) {
        test();
    }

    public static void test() {
        List<WeightRandom.WeightObj<String>> weightList = new ArrayList<>();
        weightList.add(new WeightRandom.WeightObj<>("A", 20));
        weightList.add(new WeightRandom.WeightObj<>("B", 30));
        weightList.add(new WeightRandom.WeightObj<>("C", 40));
        weightList.add(new WeightRandom.WeightObj<>("D", 10));
        WeightRandom<String> wr = RandomUtil.weightRandom(weightList);
        String str = "";
        int num_a = 0, num_b = 0, num_c = 0, num_d = 0;
        int testCount = 10000;
        for (int i = 0; i < testCount; i++) {
            str = wr.next();
            switch (str) {
                case "A":
                    num_a = num_a + 1;
                    break;
                case "B":
                    num_b = num_b + 1;
                    break;
                case "C":
                    num_c = num_c + 1;
                    break;
                case "D":
                    num_d = num_d + 1;
                    break;
            }
        }
        System.out.println("A-" + num_a + "-------" + NumberUtil.div(num_a, testCount, 2) * 100+"%");
        System.out.println("B-" + num_b + "-------" + NumberUtil.div(num_b, testCount, 2) * 100+"%");
        System.out.println("C-" + num_c + "-------" + NumberUtil.div(num_c, testCount, 2) * 100+"%");
        System.out.println("D-" + num_d + "-------" + NumberUtil.div(num_d, testCount, 2) * 100+"%");
    }


}

执行结果

java 复制代码
A-1958-------20.0%
B-3094-------31.0%
C-3972-------40.0%
D-976-------10.0%

代码详解WeightRandom的next方法

treeMap.tailMap是Java中的一个方法,用于返回一个新的map,其中包含了原map中所有大于等于指定键的键值对。

在Java中,Map是一种将键映射到值的数据结构。其中,TreeMap是一种基于红黑树实现的有序映射。它可以按照键的自然顺序或者指定的比较器顺序对键进行排序。

tailMap方法是TreeMap类中的一个方法,用于返回一个新的TreeMap,其中包含了原TreeMap中所有大于等于指定键的键值对。这个方法的定义如下:

public SortedMap<K,V> tailMap(K fromKey)
java 复制代码
	/**
	 * 下一个随机对象
	 *
	 * @return 随机对象
	 */
	public T next() {
		if(MapUtil.isEmpty(this.weightMap)) {
			return null;
		}
		final Random random = RandomUtil.getRandom();
		final double randomWeight = this.weightMap.lastKey() * random.nextDouble();
		final SortedMap<Double, T> tailMap = this.weightMap.tailMap(randomWeight, false);
		return this.weightMap.get(tailMap.firstKey());
	}
相关推荐
LuckyLay1 分钟前
Spring学习笔记_27——@EnableLoadTimeWeaving
java·spring boot·spring
向阳121814 分钟前
Dubbo负载均衡
java·运维·负载均衡·dubbo
Gu Gu Study24 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
WaaTong1 小时前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_743048441 小时前
初识Java EE和Spring Boot
java·java-ee
AskHarries1 小时前
Java字节码增强库ByteBuddy
java·后端
小灰灰__1 小时前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭1 小时前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果2 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林2 小时前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac