-
2019-09-12 09:26:35
最近公司有业务需求:要求实现批量分配操作,详情如下:
- 选择多个客户
- 选择多个员工
- 给每个员工分配客户
- 要求分配的客户数量尽量平均
- 选择的员工数大于选择的客户数时,一个员工分配一个客户,不够的就不分配
- 选择的员工数等于客户数时,一个员工对应一个客户
- 分配的客户最好是随机的。
为了实现上述需求,需要设计一个随机平均分配算法
- 一开始我的设计思路比较简单,遍历员工集合和客户集合,依次分配单个客户给每个员工,直到分完为止,但是这种实现效率很低,也达不到随机的效果。
- 转变思路,先分析、设计数据存储结构,入参为两个List<String>集合,返回数据类型为:
一、 Map<String, List<String>>,每个员工作为key,value为分配的客户列表;
二、List<Map<String, List<String>>>,员工作为key,value为分配给他的客户,每个员工-客户列表都对应一个Map<String, List<String>>集合,这样所有的员工-客户列表组合成一个List<Map<String, List<String>>>集合
最终我采用了第二种数据结构,下面是实现代码:
import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * @author gxl * @version 1.0 * @description 平均分配算法 * @date 2019-09-11 08:53 */ public class AverageDataUtil { /** * 定义存储待分配数据集合 */ private static List<String> list = Lists.newArrayList(); /** * 定义存储分组数据的结构,Map去除泛型,适配多种数据类型格式,使用时需注意 */ private static List<Map> los = Lists.newArrayList(); /** * 供外部调用的平均分配方法 * * @param visitorIds 客户列表 * @param sellerIds 员工列表 * @return List<Map> */ public static List<Map> averageData(List<String> visitorIds, List<String> sellerIds) { initCollections(visitorIds, sellerIds); if (visitorIds.size() >= sellerIds.size()) { groupByData(los.size()); return getMaps(); } else { groupByData(list.size()); return getMaps(); } } /** * 返回数据,清空静态缓存 * * @return List<Map> */ @NotNull private static List<Map> getMaps() { List<Map> listMap = Lists.newArrayList(); listMap.addAll(los); //清空静态数据 los = Lists.newArrayList(); list = Lists.newArrayList(); return listMap; } /** * 分配数据 * * @param size 分组大小 */ private static void groupByData(int size) { List<String> augmented = list; List<List<String>> lists = chunk2(augmented, size); for (int i = 0; i < size; i++) { Map map = los.get(i); Iterator iterator = map.keySet().iterator(); if (iterator.hasNext()) { String next = (String) iterator.next(); map.put(next, lists.get(i)); } } } /** * 初始化集合数据 * * @param visitorIds 待分配数据 * @param sellerIds 分配目标 */ private static void initCollections(List<String> visitorIds, List<String> sellerIds) { //每次调用前清空数据 if (list.size() > 0) { list = Lists.newArrayList(); } if (los.size() > 0) { los = Lists.newArrayList(); } list.addAll(visitorIds); List<Map<String, List<String>>> list1 = new ArrayList<>(); for (String sellerId : sellerIds) { Map<String, List<String>> map = new HashMap<>(16); List<String> list = new ArrayList<>(); map.put(sellerId, list); list1.add(map); } los.addAll(list1); } /** * 分组数据-核心算法,勿动 * * @param list 需分配数据 * @param group 分组大小 * @param <T> 分组数据泛型 * @return 分组结果 */ private static <T> List<List<T>> chunk2(List<T> list, int group) { if (CollectionUtils.isEmpty(list)) { return Lists.newArrayList(); } List<List<T>> result = Lists.newArrayList(); Map<Integer, Set<T>> temp = Maps.newHashMap(); for (int i = 0; i < list.size(); i++) { if (temp.containsKey(i % group)) { Set<T> ts = temp.get(i % group); ts.add(list.get(i)); temp.put(i % group, ts); } else { Set<T> ts = Sets.newHashSet(); ts.add(list.get(i)); temp.put(i % group, ts); } } for (Set<T> ts : temp.values()) { result.add(Lists.newArrayList(ts)); } return result; } public static void main(String[] args) { List<String> visitorIds = new ArrayList<>(); visitorIds.add("aa"); visitorIds.add("bb"); visitorIds.add("cc"); visitorIds.add("dd"); visitorIds.add("ee"); visitorIds.add("ff"); visitorIds.add("gg"); visitorIds.add("hh"); visitorIds.add("ii"); visitorIds.add("jj"); visitorIds.add("kk"); List<String> sellerIds = new ArrayList<>(); sellerIds.add("11"); sellerIds.add("22"); sellerIds.add("33"); sellerIds.add("44"); sellerIds.add("55"); sellerIds.add("66"); sellerIds.add("77"); sellerIds.add("88"); sellerIds.add("99"); sellerIds.add("1010"); sellerIds.add("1111"); List<Map> maps = averageData(visitorIds, sellerIds); System.out.println(maps); } }
这个代码可能还存在部分问题,可以继续优化改进,有什么建议的话,可以在评论区回复,毕竟我也只是个码农,对算法什么的不是很了解 - -
更多相关内容 -
java实现数据平均分配
2020-09-21 16:23:06//分配承接人 List<String> nameList=new ArrayList<>(); nameList.add("张三"); nameList.add("王五"); nameList.add("赵六"); //待分配人员 List<String> clientList=new ArrayList<>();...我这里是结合mysql的 limit 属性写的
//分配承接人 List<String> nameList=new ArrayList<>(); nameList.add("张三"); nameList.add("王五"); nameList.add("赵六"); //打乱list顺序,这样避免余数每次都分配到第一个人上面 Collections.shuffle(nameList); //待分配人员 List<String> clientList=new ArrayList<>(); clientList.add("客户1"); clientList.add("客户2"); clientList.add("客户3"); clientList.add("客户4"); clientList.add("客户5"); clientList.add("客户6"); clientList.add("客户7"); //总客户数 Integer clientCount=clientList.size(); //总分配承接人数 Integer userCount=nameList.size(); //除不净取余数 Integer remainderCount=clientCount%userCount; //每个人分配数 Integer divideCount=clientCount/userCount; //余数开始数 Integer startCount=0; System.out.println("总客户数:"+clientCount+" 总销售数:"+userCount+" 余数:"+remainderCount+" 除数:"+divideCount); //第一次分配 for(int i=0;i<userCount;i++){ System.out.println(nameList.get(i)+":"+i*divideCount+"---"+divideCount*(i+1)); //提示:update xx set xx='xx' where xx in (select id from xx limit i*divideCount,divideCount*(i+1)) if(i==userCount-1){ startCount=divideCount*(i+1); } } //第二次分配 if(remainderCount>0){ //取出剩余待分配数据 System.out.println(startCount+"---"+clientCount); //循环查出来的集合 for (int j=0;j<remainderCount;j++){ System.out.println(nameList.get(j)); } } //从程序方向出发,我想批量修改比一个一个修改快把,有更好的建议可以提出来
第一次结果最后余数分配给:张三
结果最后余数分配给:赵六 -
Java 实现两个List数据平均随机分配
2021-04-28 14:34:50先说场景: 有一批客户要分配到销售手里进行...纯随机分配,不按照顺序,但保证数量是平均的。 public static void main(String[] args) { List<String> staffList = new ArrayList<>();// 销售列表 st先说场景: 有一批客户要分配到销售手里进行维护,一个客户的list集合,一个销售的list集合,要让销售分到的客户一样多,除非分配到最后客户数量不够每一个销售了,才进行随机分配,销售之间的客户数量只有一个客户数量之差。
纯随机分配,不按照顺序,但保证数量是平均的。
public static void main(String[] args) { List<String> staffList = new ArrayList<>();// 销售列表 staffList.add("张三"); staffList.add("李四"); staffList.add("王五"); List<String> usertList = new ArrayList<>(); // 客户列表 usertList.add("客户1"); usertList.add("客户2"); usertList.add("客户3"); usertList.add("客户4"); usertList.add("客户5"); usertList.add("客户6"); usertList.add("客户7"); usertList.add("客户8"); int staffCount = staffList.size(); //销售数量 int userCount = usertList.size();//客户数量 Random random = new Random(); // 随机数 int staffCount1 = staffCount; // 定义一个销售固定数量 List<String> staffList1 = new ArrayList<>(); staffList1.addAll(staffList);// 定义一个销售固定值 for (int i = 0; i < userCount; i++) { int nextInt = random.nextInt(staffCount1); System.out.println(usertList.get(i) +"--->归属销售为:"+staffList.get(nextInt)); staffCount1--; staffList.remove(nextInt); if (staffCount1 == 0) { staffCount1 = staffCount; staffList.addAll(staffList1); } } }
可以看出来分配的顺序是乱的,但肯定的是每个销售每一轮都可以分配到,不会造成不平均的情况,最后的余下的客户就要看运气了,也可以做成按顺序分配,就把随机数替换成0就可以。这样最后余下的客户,就要按照销售的排序分配了。
-
java平均分配算法
2021-02-13 02:03:14// 分组排序后的数据 for (int i = 0; i ; i++) { List getPerson = new ArrayList(); for (int j = 0; j ; j++) { int index = 0; if (j == 0) { index = i + j; } else { index = (j) * groupCount + i; } if...public class Fenpei {
static List listCus = new ArrayList();
static List persons = new ArrayList();
// static Map result = new HashMap();
static List result = new ArrayList();
/**
* @param args
*/
public static void main(String[] args) {
int k = 0;
List l = new ArrayList();
// 发、数量
for (int i = 0; i < 20; i++) {
listCus.add(i);
}
// 人
for (int j = 0; j < 5; j++) {
persons.add("person" + j);
}
// System.out.println(persons.size());
int personSize = persons.size();
for (int i = 0; i < listCus.size(); i++) {
// System.out.println(i);
// System.out.println(persons.get(i%personSize));
Persons p = new Persons();
p.setI(i);
p.setPersonname(persons.get(i % personSize));
result.add(p);
}
Iterator it = result.iterator();
while (it.hasNext()) {
Persons p = (Persons) it.next();
System.out.println("哪个人 => " + p.getI() + " 分配到 "
+ p.getPersonname());
}
// for (int j = 1; j < persons.size() + 1; j++) {
// System.out.println(j);
// }
}
public static class Persons {
private Integer i;
private String personname;
public Integer getI() {
return i;
}
public void setI(Integer i) {
this.i = i;
}
public String getPersonname() {
return personname;
}
public void setPersonname(String personname) {
this.personname = personname;
}
}
}
第二种方法
public class FenpeiRen {
/**
* @param args
*/
public static void main(String[] args) {
Person p1 = new Person("NAME1", 201);
Person p2 = new Person("NAME2", 233);
Person p3 = new Person("NAME3", 189);
Person p4 = new Person("NAME4", 198);
Person p5 = new Person("NAME5", 164);
Person p6 = new Person("NAME6", 181);
Person p7 = new Person("NAME7", 212);
Person p8 = new Person("NAME8", 205);
Person p9 = new Person("NAME9", 192);
Person p10 = new Person("NAME10", 241);
Person p11 = new Person("NAME11", 136);
Person p12 = new Person("NAME12", 201);
Person p13 = new Person("NAME13", 142);
Person p14 = new Person("NAME14", 127);
Person p15 = new Person("NAME15", 189);
Person p16 = new Person("NAME16", 221);
List personList = new ArrayList();
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.add(p4);
personList.add(p5);
personList.add(p6);
personList.add(p7);
personList.add(p8);
personList.add(p9);
personList.add(p10);
personList.add(p11);
personList.add(p12);
personList.add(p13);
personList.add(p14);
personList.add(p15);
personList.add(p16);
sort(personList,5);
}
/**
* 分组函数
*
* @param personList
* 总人数列表
* @param groupCount
* 分组数量
*/
static void sort(List personList, int groupCount) {
// 取得总人数
int personSize = personList.size();
// 如果分组数量小于personsize,则分组
if (groupCount <= personSize) {
// 先排序
Collections.sort(personList, new Comparator() {
public int compare(Person p1, Person p2) {
return p1.get_capability().compareTo(p2.get_capability());
}
});
// 可以取多少次
int qU = (personSize / groupCount) + 1;
List> pList = new ArrayList>();
// 排序后的数量
List> sortList = new ArrayList>();
// 分组排序后的数据
for (int i = 0; i < qU; i++) {
List getPerson = new ArrayList();
for (int j = 0; j < groupCount; j++) {
int index = 0;
if (j == 0) {
index = i + j;
} else {
index = (j) * groupCount + i;
}
if(index
getPerson.add(personList.get(index));
}
}
if(getPerson.size()>0){
sortList.add(getPerson);
}
}
//开始分配
for (int j = 0; j < groupCount; j++) {
List listPerson = new ArrayList();
boolean sort = true;
for (int i = 0; i < sortList.size(); i++) {
//正向分
if(sort){
if(j
listPerson.add(sortList.get(i).get(j));
}
sort=false;
}
else{//反向分
if(groupCount-(j+1)=0){
listPerson.add(sortList.get(i).get(groupCount-(j+1)));
}
sort=true;
}
}
if(listPerson.size()>0){
pList.add(listPerson);
}
}
int m = 0;
for (List lp : pList) {
m++;
System.out.print("当前第 "+m+" 组\r\n");
int totalCa = 0;
for(Person p : lp){
totalCa = totalCa + p.get_capability();
System.out.print("能力 "+p.get_capability()+" 名字 "+p.get_name());
}
System.out.print("总能力 "+totalCa+"\r\n");
System.out.print("结束\r\n");
}
}else{
System.out.println("无法分组,分组数量大于总人数\r\n");
}
// Collection.sort();
}
}
分享到:
2010-05-07 13:26
浏览 9489
评论
1 楼
qiankai86
2013-01-06
Thank you!
-
算法学习,java实现数据随机平均分配
2020-11-18 19:43:06直接上代码,不啰嗦,复制可... //分配承接人 List<String> nameList = new ArrayList<>(); nameList.add("张三"); nameList.add("王五"); nameList.add("赵六"); nameList.add("李四"); //打乱li -
Java平均分配算法
2019-08-09 15:07:011万个设备的IMEI固定且尽量平均的分配到四个组。 算法 算法来自文章【数据结构与算法】一致性Hash算法及Java实践 public static int FnvHash(String key) { final int p = 16777619; long hash = (int) 2166136261... -
java实现将任务轮流分给每一个人,自动派单分配任务,java任务平均分配制度
2019-10-22 11:14:53业务员提交的订单分配给3位主管中任意一位去审核,业务主管提交的订单分配给另外两位去审核 即业务主管自己不能审核自己提交的订单. 例如: 当业务员提交订单1时,将该订单分配给主管A去审核, 当业务员提交订单2时... -
JAVA按金额平均分配任务量,随机分配,指定数量分配算法实例
2019-01-11 11:22:21按金额平均分配任务量算法实例需求背景思路分析代码实现 需求背景 需要批量分配订单给人员,尽量保证分配到每个人的订单金额相近。 思路分析 比如100个任务,每个任务ID和金额及号为(T100,100)…(t1,1)。第一轮... -
JAVA实现平均分配N人 (分配到的数量和总金额近似相等)
2018-05-16 10:49:22//需要分配的人员集合(list) //将人员集合顺序随机打乱 因为第一人分配到的案件总金额是最大的 Collections.shuffle(list); final int size =list.size(); //将list转换成数组userList... -
java实现金额近似平均分配
2015-06-08 06:39:49有一批不同金额的数据,需要按金额分配给系统内的用户,比如 数据1:3000,数据2:2000,数据3:4900,那么分配给2个用户的话,肯定是A用户分配数据1跟数据2,B用户分配数据3,这样才能做到近似的金额平均。... -
Java实现将List中的数据平均分成多个List
2021-04-21 17:04:32* 将一组数据平均分成n组 * @param source 要分组的数据源 * @param n 平均分成n组 * @param <T> * @return */ public static <T> List<List<T>> averageAssign(List<T> ... -
Java 实现将List平均分成若干个集合
2021-03-14 17:51:531.初衷是由于调用银行接口的批量处理接口时,每次最多只能处理500条数据,但是当数据总数为510条时。我又不想第一次调用处理500条,第二次调用处理10条数据,我想要的是每次处理255条...import java.util.ArrayList... -
平均分配算法
2019-10-29 01:58:46最近公司有业务需求:要求实现批量分配操作,详情如下: 选择多个客户 ...为了实现上述需求,需要设计一个随机平均分配算法 一开始我的设计思路比较简单,遍历员工集合和客户集合,依次分配单个客户给每个... -
java 如何把一堆数平均分成N份
2021-02-27 17:35:08均分和尾差:header('Content-Type: text/plain; charset=utf-8');function tail($num, $fen) {$avg = bcdiv($num, $fen, 2);$tail = bcsub($num, $avg*($fen-1), 2);echo $num.'='.str_repeat($avg.'+', $fen-1).$... -
Java数据结构与算法入门
2018-04-29 11:53:50第一部分:Java数据结构要理解Java数据结构,必须能清楚何为数据结构?数据结构:Data_Structure,它是储存数据的一种结构体,在此结构中储存一些数据,而这些数据之间有一定的关系。而各数据元素之间的相互关系,又... -
java抓取东方财富股票数据(附源码)
2021-03-21 10:31:20背景前段时间给朋友写了一个自动抓取同花顺股票数据的程序,不少人觉得不错。这几天后台有粉丝给我留言让我也抓一下东方财富的数据,说东方财富的数据特别难抓,我还真不一定能搞得定。本来我是一个德艺双磬且... -
一种基于平均思想的任务分配算法
2017-08-28 19:37:52假设现在有20个任务需要分配给员工去做,但是每个员工手头上还有未完成的任务,且未完成任务数不同。 -
Java程序使用数组计算平均值
2021-02-26 19:56:36Java程序使用数组计算平均值在此程序中,您将学习计算Java中给定数组的平均值。示例:使用数组计算平均值的程序publicclassAverage{publicstaticvoidmain(String[]args){double[]numArray={45.3,67.5,-45.6,20.34,... -
java大数据处理总结
2020-07-27 23:04:082.其次需要对业务服务器和业务支撑服务器进行合理的分层,并且采用并行计算和分布式算法对大量计算进行处理,并且在开发的过程中需要采用JavaSDK中并发包(Concurrency)进行编码实现。 3.存储层需要. -
Java 将List平均分成若干个集合
2018-04-16 13:13:031.初衷是由于调用银行接口的批量处理接口时,每次最多只能处理500条数据,但是当数据总数为510条时。我又不想第一次调用处理500条,第二次调用处理10条数据,我想要的是每次处理255条数据。...import java.util.Ar... -
JAVA使用线程池查询大批量数据
2022-05-06 17:33:09Java使用多线程查询大批量数据 -
实现数据按条数,按比例,按平均分配
2019-09-13 03:28:12import java.util.ArrayList; import java.util.List; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.citic... -
Java8 Stream 数据流,大数据量下的性能效率怎么样?
2021-03-31 10:09:17来源:blog.csdn.net/Al_assad/article/details/82356606Stream 是Java SE 8类库中新增的关键抽象,它被定义于 java.util.... -
java使用多线程查询大批量数据
2021-03-08 08:59:40前言在某些时候,一旦单表数据量过大,查询数据的时候就会变得异常卡顿,虽然在大多数情况下并不需要查询所有的数据,而是通过分页或缓存的形式去减少或者避免这个问题,但是仍然存在需要这样的场景,比如需要导出一... -
java数据结构与算法之顺序表与链表深入分析
2016-11-05 16:24:30开篇直接奔主题,无论是顺序表还是链表,它们都是...线性表抽象数据类型概述 线性表的顺序存储设计与实现顺序表 1 顺序存储结构的设计原理概要 2 顺序存储结构的实现分析 3 顺序存储结构的效率分析 线性表的链式存 -
java多线程并行处理List集合数据
2021-03-24 12:45:51前言碎语最近可能要批量处理一些数据,准备使用多线程来助力,回顾了下多线程的一些开发技巧,下面是多线程并行处理List的一个小例子代码看关键/*** @author kl by 2016/6/25* @boke www.kailing.pub*/public class ... -
Java 基础高频面试题(2022年最新版)
2021-03-31 23:39:26最新 Java 基础高频面试题 -
java,如何处理大批量数据插入
2021-01-12 12:33:06由于做公司业务,由于数据量太大,一条条插入数据非常缓慢。(记得是插入60w单表数据,就要半个多小时,处理完后只需要几秒了) 后来,自己操作的是通过拼接sql语句,比如 insertintopersons (name, age) values ... -
如何理解并掌握 Java 数据结构
2019-11-13 11:11:45Jack和大家一起来重温《Java数据结构》经典之作。 第一部分:Java数据结构 要理解Java数据结构,必须能清楚何为数据结构? 数据结构: Data_Structure,它是储存数据的一种结构体,在此结构中储存一些数据,而这些...