使用多种方法对集合,对象,Map进行排序

本文介绍了四种在Java中对集合、对象和Map进行排序的方法:1) 实现Comparator进行排序;2) 实现Comparable接口并重写CompareTo方法;3) 使用自定义工具类按字段排序对象数组;4) 根据属性对List<List<String>>排序。文章详细讲解了每种方法的实现过程,并提到了在某些情况下需遵循的排序原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.实现Comparator进行排序

创建需要排序对象

/**
 * @author wangli
 * @create 2022-08-17 17:17
 */
@Data
public class TotalNumDto {
    @ApiModelProperty("工单总量")
    private Integer workNum;

    @ApiModelProperty("同比数")
    private Integer yoyNum;

    @ApiModelProperty("环比数")
    private Integer qoqNum;
}

实现Comparator的compare方式实现排序

    @Test
    public void test2(){
        List<TotalNumDto> totalNumDtoList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            TotalNumDto totalNumDto = new TotalNumDto();
            totalNumDto.setWorkNum(i*2+1);
            totalNumDtoList.add(totalNumDto);
        }
        System.out.println("排序前 = " + totalNumDtoList);
        Collections.sort(totalNumDtoList, new Comparator<TotalNumDto>() {
            @Override
            public int compare(TotalNumDto o1, TotalNumDto o2) {
                //顺序
                //return o1.getWorkNum()-o2.getWorkNum();
                //逆序
                return o2.getWorkNum()-o1.getWorkNum();
            }
        });
        System.out.println("排序后 = " + totalNumDtoList);
    }

打印结果如下

排序前 = [

TotalNumDto(workNum=1, yoyNum=null, qoqNum=null),

TotalNumDto(workNum=3, yoyNum=null, qoqNum=null),

TotalNumDto(workNum=5, yoyNum=null, qoqNum=null)]
排序后 = [

TotalNumDto(workNum=5, yoyNum=null, qoqNum=null),

TotalNumDto(workNum=3, yoyNum=null, qoqNum=null),

TotalNumDto(workNum=1, yoyNum=null, qoqNum=null)]

比较它的两个参数的顺序。返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个

当compare方法返回1时需要交换这两个数的位置,通过算法循环从而达到不断交换位置实现排序

 2.实现Comparable接口,然后重写CompareTo方法。

编写对象实现Comparable接,重写CompareTo

/**
 * @author wangli
 * @create 2022-08-17 17:17
 */
@Data
public class TotalNumDto implements Comparable<TotalNumDto> {
    @ApiModelProperty("工单总量")
    private Integer workNum;

    @ApiModelProperty("同比数")
    private Integer yoyNum;

    @ApiModelProperty("环比数")
    private Integer qoqNum;

    public TotalNumDto(Integer workNum, Integer yoyNum, Integer qoqNum) {
        this.workNum = workNum;
        this.yoyNum = yoyNum;
        this.qoqNum = qoqNum;
    }

    @Override
    public int compareTo(TotalNumDto o) {
        //按照工单总量排序
        int i = this.getWorkNum().compareTo(o.getWorkNum());
        //如果工单总量一致按照同比数排序
        if (i == 0) {
            i = this.getYoyNum().compareTo(o.getYoyNum());
            //如果工同比数一致按照环比数排序
            if (i == 0) {
                i = this.getQoqNum().compareTo(o.getQoqNum());
            }

        }
        return i;
    }
}

直接调用方法实现排序

    @Test
    public void test3(){
        List<TotalNumDto> totalNumDtoList = new ArrayList<>();
        totalNumDtoList.add(new TotalNumDto(3,4,12));
        totalNumDtoList.add(new TotalNumDto(3,2,13));
        totalNumDtoList.add(new TotalNumDto(9,1,14));
        System.out.println("排序前");
        totalNumDtoList.forEach(System.out::println);
        System.out.println("排序后");
        totalNumDtoList.stream().sorted().forEach(System.out::println);
    }

按顺序排序输出

 3.使用字段对对象数组进行排序

此处是自己编写的工具类,通过输入list对象数组和需要排序的字段以及排序方式,进行排序

/**
 * @author wangli
 * @create 2022-08-17 14:13
 */
public class SortListUtil<E> {

    public void SortByField(Map<String, Object> data, List<E> list){
        if (data.containsKey("sortField")&&data.containsKey("sort")){
            String method = (String) data.get("sortField");
            String order = (String) data.get("sort");
            Sort(list,method,order);
        }
    }

    /**
     * @param list 需要排序的list
     * @param method 需要排序的字段
     * @param order 排序的顺序
     */
    public void Sort(List<E> list, final String method, final String order) {
        Collections.sort(list, new Comparator<E>() {
            @Override
            public int compare(E o1, E o2) {
                int ret = 0;
                try {
                    Method method1 = o1.getClass().getMethod(method, null);
                    Method method2 = o2.getClass().getMethod(method, null);
                    //倒序
                    if (StringUtils.isNotEmpty(order) && "desc".equalsIgnoreCase(order)) {
                        ret =Integer.parseInt(method2.invoke(o2, null).toString())>
                                Integer.parseInt(method1.invoke(o1, null).toString())?1:-1;
                    }
                    else {
                        ret = Integer.parseInt(method1.invoke(o1, null).toString())>
                                Integer.parseInt(method2.invoke(o2, null).toString())?1:-1;
                    }

                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                return ret;
            }
        });
    }
}

调用工具类

    @Override
    public List<MonthlyDto> monthlySearch(Map<String, Object> data) {
        List<MonthlyDto> dtos = new ArrayList<>();
        log.info("诉求分类(月度)排序前:{}",dtos);
        SortListUtil<MonthlyDto> totalDtoSortListUtil = new SortListUtil<>();
        totalDtoSortListUtil.Sort(dtos,"getWorkNum","desc");
        totalDtoSortListUtil.SortByField(data,dtos);
        log.info("诉求分类(月度)排序后:{}",dtos);
        return dtos;
    }

因为在jdk6和jdk7底层排序方法有些不同,所以在有些情况下会报错Comparison method violates its general contract!

在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性,不然 Arrays.sort,Collections.sort

回到上面的例子,假设存在三个元素:stu1, null,stu2,则
compare(stu1, null)= 0,
compare(null, stu2) = 0,
compare(stu1,stu2) =1 很明显违反了传递性原则。

可以将代码修改为

public void SortByMap(List<E> list, final String method, final String order) {
        Collections.sort(list, new Comparator<E>() {
            @Override
            public int compare(E o1, E o2) {
                try {
                    Method method1 = o1.getClass().getMethod(method, null);
                    Method method2 = o2.getClass().getMethod(method, null);
                    if (StringUtils.isNotEmpty(order) && "asc".equalsIgnoreCase(order)) {
                        if (o1 == null) {
                            if (o2 == null) {
                                return 0;
                            }
                            return 1;
                        }
                        return Integer.parseInt(method2.invoke(o1, null).toString()) -
                                Integer.parseInt(method1.invoke(o2, null).toString());
                    }else {
                        if (o2 == null) {
                            if (o1 == null) {
                                return 0;
                            }
                            return 1;
                        }
                        return Integer.parseInt(method2.invoke(o2, null).toString()) -
                                Integer.parseInt(method1.invoke(o1, null).toString());
                    }
                } catch (Exception e){
                    e.printStackTrace();
                    log.info(e);
                    return 0;
                }
            }
        });
    }

4.根据某一属性对List<List<String>>进行排序

    /**
     * @param data 输入需要排序的参数
     * @param yList 需要排序的List<List<String>>
     * @param s 需要过滤不排序的信息
     * @param i list中需要排序的第几个字段
     * @return 排序后的List<List<String>>
     */
    public static List<List<String>> sortContainList(Map<String, Object> data, List<List<String>> yList,String s,int i) {
        if (Objects.equals(data.get("sort"), "asc")) {
            yList.sort(Comparator.comparingInt(o -> Integer.parseInt(o.get(i))));
            return yList;
        } else {
            Collections.sort(yList, (o1, o2) -> {
                if (o1.get(i).equals(s)||o2.get(i).equals(s)){
                    return 1;
                }else {
                    return Integer.parseInt(o2.get(i)) - Integer.parseInt(o1.get(i));
                }
            });
        }
        return yList;
    }


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨会停rain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值