需求背景

    需要批量分配订单给人员,尽量保证分配到每个人的订单金额相近。可以按照金额平均分配,随机分配,指定数量分配。

    思路分析

    比如100个任务,每个任务ID和金额及号为(T100,100)…(T1,1)。第一轮分配先取最大的任务金额的分配给User1,即user1拥有T100,user2分配到T99,user3分配到T98。第二轮分配最小值,User1分配T1,User2分配T2,User3分配T3,第三轮分配最大值,即User1分配T97,User2分配T96,以此类推。

    代码实现

    JDK必须是1.8及以上,代码中使用了1.8的特性,不多废话上代码

    1. import java.io.*;
    2. import java.math.BigDecimal;
    3. import java.util.ArrayList;
    4. import java.util.Comparator;
    5. import java.util.List;
    6. import java.util.Map;
    7. import java.util.concurrent.ConcurrentHashMap;
    8. import java.util.stream.Collectors;
    9. /**
    10. * @ClassName Allot
    11. * @Desc TODO
    12. * @Author chengp
    13. * @Date 2019/1/11 9:55
    14. * @Verion 1.0
    15. */
    16. public class Allot {
    17. /**
    18. * 按金额分配
    19. *
    20. * @param users 人
    21. * @param tasks 任务
    22. * @return
    23. */
    24. public static Map<String, List<DemoTask>> allotOfAmount(List<DemoUser> users, List<DemoTask> tasks) {
    25. //Collections.shuffle(users);//随机排序
    26. Map<String, List<DemoTask>> allot = new ConcurrentHashMap<>(); //保存分配的信息
    27. if (users != null && users.size() > 0 && tasks != null && tasks.size() > 0) {
    28. List<DemoTask> copyTask = depCopy(tasks);//深拷贝,在处理过程中会删除已经分配的任务此处方便记录原始数据使用
    29. for (int n = 0; n < copyTask.size() + n; n++) {
    30. if (n % 2 == 0) {
    31. copyTask = sortTask(copyTask, "desc");//正排
    32. } else {
    33. copyTask = sortTask(copyTask, "asc");//倒排
    34. }
    35. for (int j = 0; j < users.size(); j++) {
    36. if (copyTask.isEmpty()) break;
    37. if (allot.containsKey(users.get(j).getUserId().toString())) {
    38. List<DemoTask> list = allot.get(users.get(j).getUserId().toString());
    39. list.add(copyTask.get(0));//每次取排序后的第一条
    40. allot.put(users.get(j).getUserId().toString(), list);
    41. } else {
    42. List<DemoTask> list = new ArrayList<>();
    43. list.add(copyTask.get(0));
    44. allot.put(users.get(j).getUserId().toString(), list);
    45. }
    46. copyTask.remove(copyTask.get(0));//分配后删除
    47. }
    48. }
    49. }
    50. return allot;
    51. }
    52. /**
    53. * 平均分配&指定数量分配,多余的任务不予分配
    54. *
    55. * @param users 人
    56. * @param tasks 任务
    57. * @param count 每人指定分配数量
    58. * @return
    59. */
    60. public static Map<String, List<DemoTask>> allotOfAverage(List<DemoUser> users, List<DemoTask> tasks, Integer count) {
    61. Collections.shuffle(users);//随机排序
    62. Collections.shuffle(tasks);
    63. Map<String, List<DemoTask>> allot = new ConcurrentHashMap<>(); //保存分配的信息
    64. if (users != null && users.size() > 0 && tasks != null && tasks.size() > 0) {
    65. for (int i = 0; i < tasks.size(); i++) {
    66. if (count != null && (i >= count * users.size())) {
    67. break;
    68. }
    69. int j = i % users.size();
    70. if (allot.containsKey(users.get(j).getUserId().toString())) {
    71. List<DemoTask> list = allot.get(users.get(j).getUserId().toString());
    72. list.add(tasks.get(i));
    73. allot.put(users.get(j).getUserId().toString(), list);
    74. } else {
    75. List<DemoTask> list = new ArrayList<>();
    76. list.add(tasks.get(i));
    77. allot.put(users.get(j).getUserId().toString(), list);
    78. }
    79. }
    80. }
    81. return allot;
    82. }
    83. /**
    84. * 深拷贝
    85. *
    86. * @param srcList
    87. * @param <T>
    88. * @return
    89. */
    90. public static <T> List<T> depCopy(List<T> srcList) {
    91. ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
    92. try {
    93. ObjectOutputStream out = new ObjectOutputStream(byteOut);
    94. out.writeObject(srcList);
    95. ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
    96. ObjectInputStream inStream = new ObjectInputStream(byteIn);
    97. List<T> destList = (List<T>) inStream.readObject();
    98. return destList;
    99. } catch (IOException e) {
    100. e.printStackTrace();
    101. } catch (ClassNotFoundException e) {
    102. e.printStackTrace();
    103. }
    104. return null;
    105. }
    106. /**
    107. * 排序
    108. *
    109. * @param taskList
    110. * @param sort
    111. * @return
    112. */
    113. private static List<DemoTask> sortTask(List<DemoTask> taskList, String sort) {
    114. List<DemoTask> newList;
    115. if ("asc".equalsIgnoreCase(sort)) {//正序
    116. newList = taskList.stream().sorted(Comparator.comparing(DemoTask::getAmount))
    117. .collect(Collectors.toList());
    118. } else if ("desc".equalsIgnoreCase(sort)) {//倒叙 reversed()即可
    119. newList = taskList.stream().sorted(Comparator.comparing(DemoTask::getAmount).reversed())
    120. .collect(Collectors.toList());
    121. } else {
    122. newList = taskList;
    123. }
    124. return newList;
    125. }
    126. public static class DemoUser{
    127. private Integer userId;
    128. private String userName;
    129. public Integer getUserId() {
    130. return userId;
    131. }
    132. public void setUserId(Integer userId) {
    133. this.userId = userId;
    134. }
    135. public String getUserName() {
    136. return userName;
    137. }
    138. public void setUserName(String userName) {
    139. this.userName = userName;
    140. }
    141. @Override
    142. public String toString() {
    143. return "DemoUser{" +
    144. "userId=" + userId +
    145. ", userName='" + userName + '\'' +
    146. '}';
    147. }
    148. }
    149. public static class DemoTask implements Serializable{
    150. private Integer taskId;
    151. private BigDecimal amount;
    152. public Integer getTaskId() {
    153. return taskId;
    154. }
    155. public void setTaskId(Integer taskId) {
    156. this.taskId = taskId;
    157. }
    158. public BigDecimal getAmount() {
    159. return amount;
    160. }
    161. public void setAmount(BigDecimal amount) {
    162. this.amount = amount;
    163. }
    164. @Override
    165. public String toString() {
    166. return "DemoTask{" +
    167. "taskId=" + taskId +
    168. ", amount=" + amount +
    169. '}'+'\n';
    170. }
    171. }
    172. public static void main(String[] args) {
    173. List<DemoUser> userList = new ArrayList<>();
    174. DemoUser entity = new DemoUser();
    175. entity.setUserId(1);
    176. userList.add(entity);
    177. DemoUser entity2 = new DemoUser();
    178. entity2.setUserId(2);
    179. userList.add(entity2);
    180. DemoUser entity3 = new DemoUser();
    181. entity3.setUserId(3);
    182. userList.add(entity3);
    183. List<DemoTask> taskList = new ArrayList<>();
    184. DemoTask apply1 = new DemoTask();
    185. apply1.setTaskId(1);
    186. apply1.setAmount(new BigDecimal(1000));
    187. taskList.add(apply1);
    188. DemoTask apply2 = new DemoTask();
    189. apply2.setTaskId(2);
    190. apply2.setAmount(new BigDecimal(1200));
    191. taskList.add(apply2);
    192. DemoTask apply3 = new DemoTask();
    193. apply3.setTaskId(3);
    194. apply3.setAmount(new BigDecimal(800));
    195. taskList.add(apply3);
    196. DemoTask apply4 = new DemoTask();
    197. apply4.setTaskId(5);
    198. apply4.setAmount(new BigDecimal(600));
    199. taskList.add(apply4);
    200. DemoTask apply5 = new DemoTask();
    201. apply5.setTaskId(5);
    202. apply5.setAmount(new BigDecimal(1600));
    203. taskList.add(apply5);
    204. DemoTask apply6 = new DemoTask();
    205. apply6.setTaskId(6);
    206. apply6.setAmount(new BigDecimal(2100));
    207. taskList.add(apply6);
    208. DemoTask apply7 = new DemoTask();
    209. apply7.setTaskId(7);
    210. apply7.setAmount(new BigDecimal(1210));
    211. taskList.add(apply7);
    212. DemoTask apply8 = new DemoTask();
    213. apply8.setTaskId(8);
    214. apply8.setAmount(new BigDecimal(1120));
    215. taskList.add(apply8);
    216. DemoTask apply9 = new DemoTask();
    217. apply9.setTaskId(9);
    218. apply9.setAmount(new BigDecimal(1310));
    219. taskList.add(apply9);
    220. DemoTask apply10 = new DemoTask();
    221. apply10.setTaskId(10);
    222. apply10.setAmount(new BigDecimal(1050));
    223. taskList.add(apply10);
    224. DemoTask apply11 = new DemoTask();
    225. apply11.setTaskId(11);
    226. apply11.setAmount(new BigDecimal(1500));
    227. taskList.add(apply11);
    228. List<DemoTask> copyTask = depCopy(taskList);
    229. Map<String, List<DemoTask>> map = allotOfAmount(userList,copyTask);
    230. System.out.println(map);
    231. }
    232. }