【Java】带权重的随机算法

一、引入

image-20240505170956670

这种带权重的随机是非常常见的,例如现在最后的微服务架构,就用到了这种随机算法。

其中这里的 带权重随机算法 还是很重要的:在以后,我们会学习到微服务架构,那为什么会有微服务呢?

其实就是因为现在上网的人太多了,一台服务器扛不住了,就需要将一个大项目拆分成n个小项目,部署在n个服务器中。

但是这就会有一个小问题:用户在上网的时候,我也不知道访问哪个服务器。

所以在中间就会有一个服务网关,它会根据一些算法计算出,现在哪台服务器的压力还比较小。

其中有一个算法叫做:带权重的随机,随机到哪台服务器,用户就会去访问所对应的服务器,这样的好处就是可以能让我们的项目去被更多的人访问。

一开始我们可以给每台服务器都设置权重为1,那就表示每台服务器所随机到的概率是一样的。

image-20240505171537016

但是假设,现在有一台服务器访问的人数太多了,此时我们就可以将它的权重降低,如果降到0的话,就不会再随机到这台服务器了。


二、梳理过程

在本地文件中,在准备数据的时候,需要给每个学生都设置权重,最初每个学生的权重都是1,就表示每个人被随机到的概率是一样的。

这个概率我们也会称之为 权重比,使用 个人权重 ÷ 总权重 = 每个人的权重占比

现在在文件中总共有十个人,总权重就是 10,它里面每个人的权重占比就是 0.1,即 10% 的概率。

那么这 10% 的概率怎么去计算呢?

在之前我们曾经说了一个办法, 70%的概率随机到男生30%的概率随机到女生,此时我们可以往一个集合中添加 7个1,和3个0,根据 10 的占比情况来决定概率,这种方法是可以的,但是它是适合于数据量比较少的情况,一旦数据比较多,就不合适了。

男生、女生只有两种,可以用 10 来表示,那如果有十种数据、一百种数据呢,就没有办法进行表示了。

因此我们需要来学习一种新办法:求出每一种数据的权重占比范围。

画个数轴来理解一下,既然每个学生概率都是 10%,此时就可以将数轴中的 0.01.0 去分成十等分,每一个学生占据其中的一份。

image-20240505173006581

因此这里的权重占比可以这么去理解:假设现在随机到 0.00.1 之间就表示是第一位同学;随机到 0.10.2 之间就表示是第一位同学…以此类推

image-20240505173038548

三、代码实现

首先检查数据,注意除了姓名、性别、年龄外,还需要有权重

image-20240505173156786

由于现在学生中的属性比较多,因此我们最好新建一个JavaBean类,在JavaBean类中定义四个属性,统一管理,这样会更方便一些。

成员变量里面的属性顺序 最好跟 文件中的顺序保持一致

Student.java

public class Student {
    private String name;
    private String gender;
    private int age;
    private double weight;

    //空参构造、全参构造、set/get方法
    
    //改写toString的原因结合下面代码观看
    public String toString() {
        return name + "-" + gender + "-" + age + "-" + weight;
    }
}

测试类

//1.把文件中所有的学生信息读取到内存中,并封装成一个Student对象,再方法集合里面,这样我们才能统一的进行管理
ArrayList<Student> list = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader("myiotest\\src\\com\\itheima\\myiotest6\\names.txt"));
String line;
while((line = br.readLine()) != null){
    String[] arr = line.split("-");
    Student stu = new Student(arr[0], arr[1],Integer.parseInt(arr[2]), Double.parseDouble(arr[3]));
    list.add(stu);
}
br.close();

//接下来就是要将每个人的权重占比给算出来:个人权重 ÷ 总权重 = 每个人的权重占比
//2.计算权重的总和
double weight = 0;
for (Student stu : list) {
    weight = weight + stu.getWeight();
}

//3.计算每一个人的实际占比存起来,这里可以用数组也可以用集合
//[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
double[] arr = new double[list.size()];
int index = 0;
for (Student stu : list) {
    arr[index] = stu.getWeight() / weight;
    index++;
}

//4.计算每一个人的权重占比范围
//第一个人的范围是0 ~ 0.1,第二个人的范围是0.1~0.2,我们需要想清楚0.2是怎么来的,是不是前一个人0.1的基础上,再去加上自己本身?
//第三个人的范围也是在前一个人的基础上(0.2)加上自己本身的范围0.1,就变成了0.3
for (int i = 1; i < arr.length; i++) {
    arr[i] = arr[i] + arr[i - 1];
}
//此时如果直接打印arr,有些小数是不精确的,但是这个不精确对结果影响的不是很大,是在我们能接受范围之内的。

//5.随机抽取
//获取一个0.0~1.0之间的随机数
double number = Math.random();
//判断number在arr中的位置
//由于在arr中数据是升序排列的,因此可以使用二分查找法
//方法回返回: - 插入点 - 1
//插入点 = -方法回返回 - 1
//获取number这个数据在数组当中的插入点位置
int result = -Arrays.binarySearch(arr, number) - 1;
//获取到插入点的位置后,我们就知道是哪个学生了
Student stu = list.get(result);
System.out.println(stu);

//6.修改当前学生的权重
double w = stu.getWeight() / 2;
stu.setWeight(w);

//7.把集合中的数据再次写到文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\src\\com\\itheima\\myiotest6\\names.txt"));
//需要按照指定的格式进行拼接太麻烦了,此时我们可以直接改写toString方法,此时我们就不需要多次调用get方法进行拼接了。
for (Student s : list) {
    bw.write(s.toString());
    bw.newLine();
}
bw.close();
  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值