关于Map类型的List集合根据key值排序的方法

第一次写这个有点小激动,hhhhha,最近开发遇到这个需求;
原本是想这样写①,但是不行诶;
随后这样写②,好像可行,但是代码看起来有点不舒服;
强迫症严重,试着写个公共方法去调用。
(11.18更新了多重排序版本)

//方式一
List<Map<String, Object>> sortList = list1.stream()
                .sorted(Comparator.comparing(x -> x.get("id")).reversed())
                .collect(Collectors.toList());
//方式二
List<Map<String, Object>> sortList = list1.stream()
                .sorted((o1, o2) -> Integer.compare(
                        Integer.parseInt(o1.get("id").toString()), 
                        Integer.parseInt(o2.get("id").toString()))
                ).collect(Collectors.toList());

1.基于List的sort方法编写的排序

应该会有点局限性,各位根据自己的需求完善,考虑是int类型单独做比较,其他类型按字符串比较。

package com.sinoyd.util.utilsstream;

import java.math.BigDecimal;
import java.text.Collator;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 作者:xxx
 * 创建时间:2019/10/22 9:14
 * 版本:1.0
 * 描述:排序扩展类
 */
public class SortUtil {
    private static final Comparator<Object> CHINA_COMPARE = Collator.getInstance(Locale.CHINA);

    /**
     * map类型的集合排序,集合顺序中m1实则在m2之后,多重排序
     *
     * @param list   集合
     * @param sortBy 排序的key值,如a+b-
     */
    public static void listSort(List<Map> list, String sortBy) {
        LinkedHashMap<String, Boolean> sort = getSortBy(sortBy);
        list.sort((m1, m2) -> {
            int compare = 0;
            for (Map.Entry<String, Boolean> entry : sort.entrySet()) {
                String key = entry.getKey();

                if (entry.getValue()) {//是否倒序
                    compare = compare(m2.get(key), m1.get(key), -1, 1);
                } else
                    compare = compare(m1.get(key), m2.get(key), 1, -1);

                if (compare != 0) {
                    return compare;
                }
            }
            return compare;
        });
    }

    /**
     * map类型的集合排序,集合顺序中m1实则在m2之后,只能单key值排序
     *
     * @param list 集合
     * @param key  排序的key值
     * @param isDesc 是否倒序
     */
    public static void listSort(List<Map> list, Object key, boolean isDesc) {
        if (isDesc)
            list.sort((m1, m2) -> compare(m2.get(key), m1.get(key), -1, 1));//倒序
        else
            list.sort((m1, m2) -> compare(m1.get(key), m2.get(key), 1, -1));//正序
    }

    /**
     * 处理排序机制
     *
     * @param sort 排序字符串 如a+b-
     */
    private static LinkedHashMap<String, Boolean> getSortBy(String sort) {
        String pattern = "[^+-][a-zA-z_]+[+-]*";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(sort);
        LinkedHashMap<String, Boolean> map = new LinkedHashMap<>();
        while (m.find()) {
            String group = m.group();
            map.put(group.replace("+", "").replace("-", "").trim(), group.contains("-"));
        }

        return map;
    }

    /**
     * 当比较结果大于0位置不变,小于0位置互换,等于0似乎是比较其他东西
     * 当两个比较值为都为空时,不改变所有空值的添加顺序 = 1
     *
     * @param r1 当o1为空时.是否交换位置;1不交换-1交换
     * @param r2 当o2为空时.是否交换位置;1不交换-1交换
     */
    private static int compare(Object o1, Object o2, int r1, int r2) {
        if (o1 == null && o2 == null) {
            return 1;
        } else if (o2 == null) {
            return r2;
        } else if (o1 == null) {
            return r1;
        } else {
            String s1 = o1.toString();
            String s2 = o2.toString();
            if (o1 instanceof Number && o2 instanceof Number) {
                return new BigDecimal(s1).compareTo(new BigDecimal(s2));
            }
            return CHINA_COMPARE.compare(s1, s2);
        }
    }
}

上面的代码直接复制就好了,那开始测试吧

2.测试效果

    public static void main(String[] args) {
        List<Map> list = new ArrayList<>();
        list.add(build(1.15, "额"));
        list.add(build(1.24, "3.54"));
        list.add(build(1.24, "9.11"));
        list.add(build(null, "9.12"));
        list.add(build(-2.54, "啊"));
        list.add(build(2.22, "出"));
        list.add(build(2.22, "的"));
        list.add(build(-4.11, "个"));
        list.add(build(4.12, "2"));
        list.add(build(4.11, "1"));

//        SortUtil.listSort(list, "bb", true);
        SortUtil.listSort(list, "aa-bb-");

        System.out.println("aa顺序" + "  " + "bb顺序");
        list.forEach(x -> {
            System.out.print(x.get("aa"));
            System.out.print("   ");
            System.out.print(x.get("bb"));
            System.out.println("");
        });
    }

    private static Map<String, Object> build(Number a, String b) {
        Map<String, Object> map = new HashMap<>();
        map.put("aa", a);
        map.put("bb", b);
        return map;
    }

emmmm,这样子还可以,考虑是将null一直放在最后面。希望对各位有所帮助,以上!

aa顺序  bb顺序
4.12   2
4.11   1
2.222.221.24   9.11
1.24   3.54
1.15-2.54-4.11null   9.12

后记,发现了点问题 已修改,另外如果key值基本变动少建议用定制dto去代替map来使用,再基于stream的Comparator类来实现排序,更可支持多排序。

你可能感兴趣的:(排序,map,stream)