使用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());
	}
相关推荐
ok!ko2 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_857589362 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰3 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
哎呦没3 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
编程、小哥哥4 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程5 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇5 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码5 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
郭二哈6 小时前
C++——模板进阶、继承
java·服务器·c++
A尘埃6 小时前
SpringBoot的数据访问
java·spring boot·后端