使用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());
	}
相关推荐
云和数据.ChenGuang6 分钟前
fastapi项目拆分实战数据模型
java·服务器·数据库·人工智能·深度学习·fastapi·强化学习
小龙报1 小时前
【优选算法】1.搜索插入位置 2.x的平方根
java·c语言·数据结构·c++·python·算法·蓝桥杯
山荷枝1 小时前
04-框架--SpringBoot
java·spring boot·后端
linux修理工1 小时前
内存占用 99% 且 Java 程序较多的优化建议
java·开发语言
weixin_460443561 小时前
企业考试系统如何对接OA、钉钉和企业微信?SSO单点登录、组织同步与权限一致性设计
java·开发语言·数据库
Sylvia33.1 小时前
篮球数据API的技术架构与工程实践:基于火星数据WebSocket实时推送体系
java·python·websocket·网络协议·架构
Hi李耶1 小时前
【LeetCode】15.三数之和
java·算法·leetcode
蔬菜_2 小时前
前端转全栈-day6(构造函数与继承)
java
程序员雷欧2 小时前
Java 反射深度解析:从原理到源码的全面剖析
java·开发语言·python
登登登__2 小时前
春秋招笔试题总结
java·开发语言