import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.ThreadLocalRandom;publicclassRedPacketUtils{/**
* 红包分配算法
*
* @param total 总金额 (单位: 分)
* @param count 总份数
* @return
*/publicstatic List<Integer>random(finalint total,finalint count){if(total <=0){thrownewIllegalArgumentException("The total must be greater than 0.");}if(count <=0){thrownewIllegalArgumentException("The count must be greater than 0.");}int restMoney = total;int restCount = count;
Random random = ThreadLocalRandom.current();
List<Integer> data =newArrayList<Integer>(count);// 随机发前 totalCount - 1 个红包, 最后一个不需要随机for(int i =0; i < count -1; i++){// 最少1分钱, 最多不超过剩下金额平均数的2倍int threshold =(restMoney / restCount *2);int item = random.nextInt(threshold)+1;
data.add(item);
restMoney -= item;
restCount--;}// 最后一个红包不需要随机
data.add(restMoney);return data;}/**
* 红包分配算法
*
* @param total 总金额 (单位: 分)
* @param count 总份数
* @param min 包下限 (单位: 分)
* @param max 包上限 (单位: 分)
* @param factor 浮动阈 [0.0f, 1.0f]
* @return
*/publicstatic List<Integer>random(finalint total,finalint count,finalint min,finalint max,finalfloat factor){if(total <=0){thrownewIllegalArgumentException("The total must be greater than 0.");}if(count <=0){thrownewIllegalArgumentException("The count must be greater than 0.");}if(min <=0){thrownewIllegalArgumentException("The min must be greater than 0.");}if(max <=0){thrownewIllegalArgumentException("The max must be greater than 0.");}if(total < count * min || total > count * max){thrownewIllegalArgumentException("The total must be between count * min and count * max.");}if(factor <0.0f|| factor >1.0f){thrownewIllegalArgumentException("The factor must be between 0 and 1.");}
Random random = ThreadLocalRandom.current();
List<Integer> data =newArrayList<Integer>(count);// 平均分配红包int avg = total / count;int rest = total - avg * count;for(int i =0; i < count; i++){
data.add(i < rest ? avg +1: avg);}// 根据浮动阈重新标定if(factor <=0|| factor >1){return data;}for(int i =0; i < count -1; i++){int itemThis = data.get(i);int itemNext = data.get(i +1);boolean isLt = itemThis < itemNext;int rangeThis = isLt ? max - itemThis : itemThis - min;int rangeNext = isLt ? itemNext - min : max - itemNext;int rangeBound =(int) Math.ceil(factor *(Math.min(rangeThis, rangeNext)+1));int mark = random.nextInt(rangeBound)+1;int rule = isLt ? mark :-mark;
data.set(i, data.get(i)+ rule);
data.set(i +1, data.get(i +1)- rule);}return data;}}