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();
}
}
有什么缺点与问题关系一起讨论进步,谢谢!!