Java 多条件复杂排序小结
前言 今天下午做了拼多多在牛客网上的在线笔试题,感觉自己的智商被鄙视到了···不过其中一道题的某一部分引起了我极大的兴趣,感觉可以总结一下,做好积累~ 题目的部分我拍照如下所示
这里面最复杂的就是第3点,对秒杀活动进行排序,排序条件多,排序条件使用各不相同,在笔试中给我带来了很大的困扰,最后当然也是没做完啦···· 解决方案 吃完晚饭开始寻找解决方法,觉得应该会很有意思,果然看到了比较好的做法,链接在这 java多条件优先级排序 — Comparator 这个方案以我这样几个月的菜鸟看来,最巧妙的就是把 多个比较器 Comparator放进一个 比较器列表 中,然后在需要时,在new一个比较器,然后在其中foreach使用各个比较器,而且注意看他代码24行的if,没有在循环中间返回结果为0的情况,而是在使用完所有比较器最后再返回0;这样就能按顺序依次使用各个比价器了。 那么回到我的题目中来 我先定义了4个比较器,分别用于4中不同项目的排序比较 //按人气从大到小对活动进行排序 private Comparator<Activity> renqiComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(goods.get(o1.goodsId).renQi == goods.get(o2.goodsId).renQi) { return 0; } else { return goods.get(o1.goodsId).renQi > goods.get(o2.goodsId).renQi ? -1 : 1; } } }; //按商品id从小到大排序 private Comparator<Activity> idComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(o1.goodsId == o2.goodsId) { return 0; } else { return o1.goodsId > o2.goodsId ? 1 : -1; } } }; //按活动开始时间从早到晚排序 private Comparator<Activity> startTimeComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(o1.startTime == o2.startTime) { return 0; } else { return o1.startTime > o2.startTime ? 1 :-1; } } }; //按活动的最后卖出时间从晚到早排序 private Comparator<Activity> sellTimeComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(o1.sellTime == o2.sellTime) { return 0; } else { return o1.sellTime > o2.sellTime ? -1 : 1; } } }; 然后定义了三个比较器列表,分别用于三种情况下的比较,然后在构造器中初始化这3个比较器列表 public Main3() { //在构造器中把这个复杂的比较器列表进行初始化 //对于进行中(未售罄)的活动,按商品人气从高到低、商品ID从小到大排序 activityComparatorList1.add(renqiComparator); activityComparatorList1.add(idComparator); //对于进行中(已售罄)的活动,按最后卖出时间从晚到早、商品人气从高到低、商品ID从小到大排序 activityComparatorList2.add(sellTimeComparator); activityComparatorList2.add(renqiComparator); activityComparatorList2.add(idComparator); //对于未开始的活动,依次按开始时间从早到晚、商品人气从高到低、商品ID从小到大排序 activityComparatorList3.add(startTimeComparator); activityComparatorList3.add(renqiComparator); activityComparatorList3.add(idComparator); } 最后再需要对活动排序的地方这样使用,针对不同阶段使用不同的比较器列表。 Collections.sort(list, new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { //在同一阶段内的比较 if(o1.limitQuantity>0 && o2.limitQuantity>0) {//进行中未售罄 for(Comparator<Activity> comparator : activityComparatorList1) { if(comparator.compare(o1, o2) < 0) { return -1; } else if(comparator.compare(o1, o2) > 0) { return 1; } } return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.limitQuantity == 0 && o2.limitQuantity == 0) {//进行中已售罄 for(Comparator<Activity> comparator : activityComparatorList2) { if(comparator.compare(o1, o2) < 0) { return -1; } else if(comparator.compare(o1, o2) > 0) { return 1; } } return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.startTime>time && o2.startTime>time) { //未开始活动 for(Comparator<Activity> comparator : activityComparatorList3) { if(comparator.compare(o1, o2) < 0) { return -1; } else if(comparator.compare(o1, o2) > 0) { return 1; } } return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } //在不同阶段的比较 if(o1.limitQuantity > 0 && (o2.limitQuantity == 0 || o2.startTime>time)) { return -1; } else if(o1.limitQuantity == 0 && o2.startTime>time) { return -1; } else { return 1; } } }); 这样我感觉是比较合理的解决了这样一个多重不同条件的比较问题,而且感觉没有使用过多的判断使得逻辑混乱。 附全部代码 这道题最后也没有放在OJ上测试过,所以可能有错,仅供参考 package com.pinduoduo; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Scanner; public class Main3 { public HashMap<Integer, Good> goods = new HashMap<>(); public ArrayList<Activity> activities = new ArrayList<>(); public List<Comparator<Activity>> activityComparatorList1 = new ArrayList<>(); public List<Comparator<Activity>> activityComparatorList2 = new ArrayList<>(); public List<Comparator<Activity>> activityComparatorList3 = new ArrayList<>(); //按人气从大到小对活动进行排序 private Comparator<Activity> renqiComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(goods.get(o1.goodsId).renQi == goods.get(o2.goodsId).renQi) { return 0; } else { return goods.get(o1.goodsId).renQi > goods.get(o2.goodsId).renQi ? -1 : 1; } } }; //按商品id从小到大排序 private Comparator<Activity> idComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(o1.goodsId == o2.goodsId) { return 0; } else { return o1.goodsId > o2.goodsId ? 1 : -1; } } }; //按活动开始时间从早到晚排序 private Comparator<Activity> startTimeComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(o1.startTime == o2.startTime) { return 0; } else { return o1.startTime > o2.startTime ? 1 :-1; } } }; //按活动的最后卖出时间从晚到早排序 private Comparator<Activity> sellTimeComparator = new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { if(o1.sellTime == o2.sellTime) { return 0; } else { return o1.sellTime > o2.sellTime ? -1 : 1; } } }; public Main3() { //在构造器中把这个复杂的比较器列表进行初始化 //对于进行中(未售罄)的活动,按商品人气从高到低、商品ID从小到大排序 activityComparatorList1.add(renqiComparator); activityComparatorList1.add(idComparator); //对于进行中(已售罄)的活动,按最后卖出时间从晚到早、商品人气从高到低、商品ID从小到大排序 activityComparatorList2.add(sellTimeComparator); activityComparatorList2.add(renqiComparator); activityComparatorList2.add(idComparator); //对于未开始的活动,依次按开始时间从早到晚、商品人气从高到低、商品ID从小到大排序 activityComparatorList3.add(startTimeComparator); activityComparatorList3.add(renqiComparator); activityComparatorList3.add(idComparator); } public int addActivity(int startTime, int endTime, int goodsId, int limitQuantity) { if(limitQuantity <= goods.get(goodsId).kuCun) { Activity activity = new Activity(); activity.startTime = startTime; activity.endTime = endTime; activity.goodsId = goodsId; activity.limitQuantity = limitQuantity; activity.id = activities.size(); activities.add(activity); return activity.id; } return -1; } public int buyGoods(int time, int activityId, int quantity) { Activity activity = activities.get(activityId); int startTime = activity.startTime; int endTime = activity.endTime; int limitQuantity = activity.limitQuantity; if(time < startTime || time >= endTime) { return -1; } else if(quantity > limitQuantity) { return -1; } else { activity.limitQuantity -= quantity; activity.sellTime = time; return 0; } } public List<Activity> getActivityList(int time) { ArrayList<Activity> list = new ArrayList<>(); for (Activity activity : activities) { if(time >= activity.startTime && time < activity.endTime) { list.add(activity); } } Collections.sort(list, new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { //在同一阶段内的比较 if(o1.limitQuantity>0 && o2.limitQuantity>0) {//进行中未售罄 for(Comparator<Activity> comparator : activityComparatorList1) { if(comparator.compare(o1, o2) < 0) { return -1; } else if(comparator.compare(o1, o2) > 0) { return 1; } } return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.limitQuantity == 0 && o2.limitQuantity == 0) {//进行中已售罄 for(Comparator<Activity> comparator : activityComparatorList2) { if(comparator.compare(o1, o2) < 0) { return -1; } else if(comparator.compare(o1, o2) > 0) { return 1; } } return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.startTime>time && o2.startTime>time) { //未开始活动 for(Comparator<Activity> comparator : activityComparatorList3) { if(comparator.compare(o1, o2) < 0) { return -1; } else if(comparator.compare(o1, o2) > 0) { return 1; } } return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } //在不同阶段的比较 if(o1.limitQuantity > 0 && (o2.limitQuantity == 0 || o2.startTime>time)) { return -1; } else if(o1.limitQuantity == 0 && o2.startTime>time) { return -1; } else { return 1; } } }); return list; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); Main3 main = new Main3(); int n = sc.nextInt(); int m = sc.nextInt(); for(int i=0; i<n; i++) { Good good = new Good(); good.id = sc.nextInt(); good.renQi = sc.nextInt(); good.kuCun = sc.nextInt(); main.goods.put(good.id, good); } sc.nextLine(); String[] ask = new String[m]; for(int i=0; i<m; i++) { ask[i] = sc.nextLine(); } for(int i=0; i<m; i++) { String[] command = ask[i].split(" "); if("add".equals(command[1])) { int time = Integer.parseInt(command[0]); int startTime = Integer.parseInt(command[2]); int endTime = Integer.parseInt(command[3]); int goodsId = Integer.parseInt(command[4]); int limitQuantity = Integer.parseInt(command[5]); System.out.println(main.addActivity(startTime, endTime, goodsId, limitQuantity)); } else if("buy".equals(command[1])) { int time = Integer.parseInt(command[0]); int activityId = Integer.parseInt(command[2]); int quantity = Integer.parseInt(command[3]); System.out.println(main.buyGoods(time, activityId, quantity)); } else if("list".equals(command[1])){ int time = Integer.parseInt(command[0]); List<Activity> list = main.getActivityList(time); for (Activity activity : list) { System.out.print(activity.id+" "); } System.out.println(); } } } } class Good { public int id; public int renQi; public int kuCun; } class Activity { public int id; public int startTime; public int endTime; public int goodsId; public int limitQuantity; public int sellTime; }