权重分配算法:三种方式实现

java实现权重分配,按不同需求三种实现方式。

不是给定需要分配的总量进行权重分配,而是不清楚需要分配的总量,对于每次分配请求指出分配的对象。

一.实体类:

package com.luck.model.pojo;

import lombok.Data;

/**
 * 分配权重类
 *
 */
@Data
public class AssignWeight {
    private String name; // 名字
    private int weight;  // 所占权重
    private int count;   // 已分配总量

}

 二:实现分配

 2.1 严格按照权重分配比例才可以进行下一个分配
   说明:如a:b:c=9:8:7的权重,需要计算a/b,b/c 与已分配的进行比较大小,必须先满足a:b=9:8才可以对c进行分配。

    /**
     * 1.并没有计算总占比
     * 缺点:对于占比另类的不太精确(如: a:b:c=9:8:7)
     * 优点:不必遍历全部集合值
     * @param list
     * @return
     */
    public static AssignWeight assign(List list) {
        list.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
        int size = list.size();
        // 相邻权重比例
        double[] weightD = new double[size - 1];
        // 相邻已分配 比例
        double[] countD = new double[size - 1];
        AssignWeight oneWeight = list.get(0);
        int weightFlag = oneWeight.getWeight();
        int countFlag = oneWeight.getCount();
        if (countFlag == 0) {
            return list.get(0);
        }
        int index = 0;
        for (int i = 0; i < size - 1; i++) {
            AssignWeight indexAssignWeight = list.get(i + 1);
            int indexWeight = indexAssignWeight.getWeight();
            int indexCount = indexAssignWeight.getCount();
            if (indexCount == 0) {
                index = i + 1;
                break;
            }
            weightD[i] = (double) weightFlag / indexWeight;
            countD[i] = (double) countFlag / indexCount;
            weightFlag = indexWeight;
            countFlag = indexCount;
            if (weightD[i] == countD[i]) {
                continue;
            }
            index = weightD[i] > countD[i] ? 0 : i + 1;
            break;
        }
        return list.get(index);
    }

2.2 均匀分配(对2.1的优化)

 说明:如a,b,c,需要计算a/b,b/c 与已分配的进行比较大小

/**
     * 2.并没有计算总占比
     * @param list
     * @return
     */
public static AssignWeight assignSpecialty(List list) {
        list.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
        int size = list.size();
        // 相邻权重比例
        double[] weightD = new double[size - 1];
        // 相邻已分配 比例
        double[] countD = new double[size - 1];
        AssignWeight oneWeight = list.get(0);
        int weightFlag = oneWeight.getWeight();
        int countFlag = oneWeight.getCount();
        if (countFlag == 0) {
            return list.get(0);
        }
        int index = 0;
        for (int i = 0; i < size - 1; i++) {
            AssignWeight indexAssignWeight = list.get(i + 1);
            int indexWeight = indexAssignWeight.getWeight();
            int indexCount = indexAssignWeight.getCount();
            if (indexCount == 0) {
                index = i + 1;
                break;
            }
            weightD[i] = (double) weightFlag / indexWeight;
            countD[i] = (double) countFlag / indexCount;
            weightFlag = indexWeight;
            countFlag = indexCount;
            if (weightD[i] == countD[i]) {
                index = i;
                continue;
            }
            if (weightD[i] > countD[i]) {
                // 已分配 < 所占权重
                index = i;
                break;
            } else if (i == size - 2){
                // 最小权重占比
                index = i + 1;
                break;
            }
        }
        return list.get(index);
    }

2.3 均匀分配

 说明:如a,b,c,需要计算a/(a+b+c),b/(a+b+c),c/(a+b+c)

    /**
     * 2
     * 缺点:遍历全部权重项
     * 优点:按照占比分配相对均匀
     * @param list
     * @return
     */
    public static AssignWeight assignUniform(List list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        int size = list.size();
        if (size == 1) {
            return list.get(0);
        }
        list.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
        int weightTotal = 0;
        int countTotal = 0;
        int[] weight = new int[size];
        int[] count = new int[size];
        for (int i = 0; i < size; i++) {
            AssignWeight indexAssignWeight = list.get(i);
            weight[i] = indexAssignWeight.getWeight();
            count[i] = indexAssignWeight.getCount();
            weightTotal += weight[i];
            countTotal += count[i];
        }
        // 权重所占比例
        double[] weightD = new double[size];
        // 已分配所占比例
        double[] countD = new double[size];
        int index = 0;
        for (int i = 0; i < size; i++) {
            weightD[i] = (double) weight[i] / weightTotal;
            countD[i] = (double) count[i] / countTotal;
            if (countD[i] >= weightD[i]) {
                continue;
            }
            index = i;
            break;
        }
        return list.get(index);
    }

 2.4随机分配

/**
     * 4.随机分配
     * @param list
     * @return
     */
    public static AssignWeight assignRand(List list) {
        int size;
        if (list == null || (size = list.size()) == 0) {
            return null;
        }
        if (size == 1) {
            return list.get(0);
        }
        int totalWeight = 0;
        int[] weightSegment = new int[size];
        for (int i = 0; i < size; i++) {
            AssignWeight indexAssign = list.get(i);
            Integer indexWeight = indexAssign.getWeight();
            totalWeight += indexWeight;
            weightSegment[i] = totalWeight;
            System.out.print(weightSegment[i] + ",");
        }
        System.out.println();
        int rand = (int) (1 + Math.random() * (totalWeight));
        System.out.println("随机数:" + rand);
        int index = 0;
        for (int i = size - 2; i >= 0; i--) {
            if (rand > weightSegment[i]) {
                index = i + 1;
                break;
            }
        }
        return list.get(index);
    }

三.测试

public static void main(String[] args) {
        List list = new ArrayList<>();
        for (int i = 10; i >= 1; i--) {
            AssignWeight assignWeight = new AssignWeight();
            assignWeight.setWeight(i);
            assignWeight.setCount(0);
            assignWeight.setName("优先级"+i);
            list.add(assignWeight);
        }
        long l = System.currentTimeMillis();
        assignChoose(list);
        System.out.println("时间间隔:" + (System.currentTimeMillis()-l));
    }
    public static void assignChoose(List list){
        for (int i = 0; i < 30; i++) {
            AssignWeight assign = assignSpecialty(list);
            System.out.println("需要新增等级为:" + assign.getWeight());
            int index = 10 - assign.getWeight();
            list.get(index).setCount(list.get(index).getCount() + 1);
            for (int j = 0; j < list.size(); j++) {
                System.out.print("weight:"+list.get(j).getWeight()+",count:"+list.get(j).getCount()+"     ");
            }
            System.out.println();
        }
    }

  有什么缺点与问题关系一起讨论进步,谢谢!!

你可能感兴趣的:(-java基础,-个人,java)