• 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;
    } 
  • 相关阅读:
    skywalking监控配置tomcat的参数
    weblogic启动受管理节点
    JavaScript中的数组遍历forEach()与map()方法以及兼容写法
    ajax与HTML5 history pushState/replaceState实例
    mongoose参考手册
    mongoose
    解决ul里最后一个li的margin问题
    前端开发中最常用的JS代码片段
    CSS3精美前端
    60个有用的css代码片段
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/10654455.html
Copyright © 2020-2023  润新知