JAVA实现自定义排序

一、需求:

最近接到一个需求,要求对成绩单的成绩进行排序。不是按照成绩排序,而是按照课程类别和上课的时间进行排序。我首先想到的是双循环,但是我认为这样的话if-else要写到猴年马月。

之后我开始回忆以前的数据结构了,不论是二分法还是快排,他们分明比较的都是数字大小啊,字符串虽然可以比较,但是现在课程的排序是人为自定义的,我怎么比较呢?

二、问题:

根据现在遇到的情况我就认为,想要排序必然要把字符串转换成数字,毕竟排序都是数字的,那么只有这样才能够直接比较。因此很自然的需要创建一个HashMap存放课程类别和它对应的大小。

成绩单长这样。
在这里插入图片描述

三、业务介绍

我这里的课程类别是一个对象,因为课程类别里面有一级学科二级学科这样,不过这是业务知识不重要,因此直接开始讲我的解决方案。在实际业务当中,数据还有老成绩和新成绩的说法,所以判断的地方非常多,有一点点小复杂。

四、代码

使用的是Collections下的sort方法,传入你需要排序的List以及排序方法。

//自定义排序1
Collections.sort(list, new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getId() - o2.getId();
    }
});

前面提到过,既然是自定义排序,那么一定要对排序的东西事先定义好排序大小。

//为给课程排序,自定义排序规则,key是course_category的id,value是排名
    private static Map<Long,Integer> zsCourseSortMap = new HashMap<>();//专硕
    private static Map<Long,Integer> xsCourseSortMap = new HashMap<>();//学硕
    static {
        xsCourseSortMap.put(1249L,0);//学位公共课(必修)
        xsCourseSortMap.put(18L,1);//学位基础课(必修)
        xsCourseSortMap.put(19L,2);//学位专业课(必修)
        xsCourseSortMap.put(20L,3);//学位专业课(选修)
        xsCourseSortMap.put(21L,4);//跨学科或跨专业课程(选修)
        xsCourseSortMap.put(23L,5);//公共选修课
        xsCourseSortMap.put(-1L,100);//其它

        zsCourseSortMap.put(1254L,0);//公共课 必修
        zsCourseSortMap.put(1265L,0);//公共课 通识
        zsCourseSortMap.put(18L,1);//学位基础课
        zsCourseSortMap.put(670L,2);//专业必修课
        zsCourseSortMap.put(671L,3);//专业选修课
        zsCourseSortMap.put(672L,4);//专业实践
        zsCourseSortMap.put(-1L,100);//
    }

解释一下,这里的Key是课程类别对象的id,value是我自定义的大小,到时候只需要判断类别的id就能判断是哪一门课类别,之所以不直接存对象是我觉得这里new对象是一件很麻烦的事情,如果还要从数据库中一个个找出来存好,或许增加了不必要的开销。使用static是因为这些资源是亘古不变的,不随对象的变化而变化。


这里介绍一下传入的成绩列表。传进去的每一个成绩实际上是一个Map而不是Score对象。因为业务上表要达到范式要求,表的属性不能要啥都有啥,很多时候是精简的,Score本身可能并不存课程类别之类的。因此实际上获取的数据是已经封装好的Map格式

List<Map<String, Object>> scoreList;
private void sortScoreListByCategory(List<Map<String,Object>> scoreList, Map<Long,Integer> degreeTypeMap) {
        Collections.sort(scoreList, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                CourseCategory o1Category = new CourseCategory();
                CourseCategory o2Category = new CourseCategory();
                if( o1.get("courseCategory") instanceof CourseCategory) { //能否转型
                    o1Category = (CourseCategory) o1.get("courseCategory");
                } else {
                    Map map1 =(Map) o1.get("courseCategory");
                    o1Category = courseCategoryRepository.findByFirstCategoryAndSecondCategory(map1.get("firstCategory").toString(), map1.get("secondCategory").toString());
                }
                if( o2.get("courseCategory") instanceof CourseCategory) {
                    o2Category = (CourseCategory) o2.get("courseCategory");
                } else {
                    Map map2 =(Map) o2.get("courseCategory");
                    o2Category = courseCategoryRepository.findByFirstCategoryAndSecondCategory(map2.get("firstCategory").toString(), map2.get("secondCategory").toString());
                }

                String o1studyTime = (String) o1.get("studyTime");
                String o2studyTime = (String) o2.get("studyTime");
                if(o1Category.getId() != o2Category.getId()) { //判断课程类别ID是否相等
                    return degreeTypeMap.get(o1Category.getId()) == null ? degreeTypeMap.get(-1L) : degreeTypeMap.get(o1Category.getId()).compareTo(degreeTypeMap.get(o2Category.getId()) == null ? degreeTypeMap.get(-1L) : degreeTypeMap.get(o2Category.getId()));
                } else if (!o1studyTime.equals(o2studyTime)){
                    return o1studyTime.compareTo(o2studyTime);
                }
                return 0;
            }
        });
    }

五、代码解释
根据最上面的格式,sort传进去一个List和comparator。degreeTypeMap是最前面第二个自定义的Map排序规则,要用到。

compare里面其实就是传进去两个List里存放的两个随意对象。因为本质是两两比较。
严谨点需要先判断,Map里取出的courseCategory(课程类别)能不能转型成课程类别,如果不能则说明是老数据(业务问题),从数据库中找出这个课程类别对象。那么至此就获取了需要比较的这两个对象的课程类别。

核心: 关键就是下面的如果课程类别的id不相等则说明要比较,然后从自定义的Map中获取这门课程类别的排序值,但是这里需要多一个判断,因为自定义排序可能有其他的类型,如果没有找到这门课的课程类别说明是其它,按照其它处理。
获取两门课的排序值以后,直接对他门进行.compareTo就行了当然相减也可以。

如果课程类别的id一样则再判断他们课程的学年就行了,这里因为学年是时间字符串,可以直接比较。

升序降序

@Override
    public int compareTo(Student o1, Student o2) {
        //降序
        //return o1.compareTo(o2);
        //升序
        return o2.compareTo(o1);        
    }

根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数

降序就是由下往上是从大到小。

暂时先这样写

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值