0 前言

对List(次要指ArrayList)和Map(次要指HashMap)的排序是最常见的业务场景,因而,有必要对其进行系统地梳理和学习,本文总结了罕用的排序办法。

1 List排序

1.1 根本数据类型的排序

a.数值型数据

// 此处包含本文波及的所有import,前面的案例不再反复import org.junit.Test;import java.text.Collator;import java.util.*;import java.util.stream.Collectors;@Testpublic void intTest() {    List<Integer> intList = new ArrayList<>();    intList.add(1);    intList.add(5);    intList.add(4);    System.out.println("原始:" + intList);    // 倒置    Collections.reverse(intList);    System.out.println("倒置:" + intList);    // 排序    intList.sort(Comparator.naturalOrder());    System.out.println("正序:" + intList);    intList.sort(Comparator.reverseOrder());    System.out.println("倒序:" + intList);}

输入后果:

原始:[1, 5, 4]倒置:[4, 5, 1]正序:[1, 4, 5]倒序:[5, 4, 1]

b.字符型数据

英文字符的排序依照字母表程序,具体操作与数值型排序相似,不再赘述。此处,特地介绍下中文字符的排序,常见的形式是以首个汉字的拼音首字母程序排。

@Testpublic void strTest() {    List<String> strList = new ArrayList<>();    strList.add("武汉");    strList.add("北京");    strList.add("上海");    System.out.println("原始:" + strList);    // 排序    Collator instance = Collator.getInstance(Locale.CHINA); // 据说遇到生僻字时会有bug,暂未波及不深究    strList.sort(instance);    System.out.println("正序:" + strList);    strList.sort(instance.reversed());    System.out.println("倒序:" + strList);}

输入后果:

原始:[武汉, 北京, 上海]正序:[北京, 上海, 武汉]倒序:[武汉, 上海, 北京]

1.2 JavaBean类型的排序

自定义一个JavaBean:

public class A implements Comparable<A> {    private String name;    private Integer order;    public A(String name, Integer order) {        this.name = name;        this.order = order;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getOrder() {        return order;    }    public void setOrder(Integer order) {        this.order = order;    }    @Override    public String toString() {        return "order=" + order+ " name=" + name;    }    @Override    public int compareTo(A a) {        return this.order.compareTo(a.getOrder());    }}

对于自定义的JavaBean类型,有以下几种常见的排序办法:

@Testpublic void objectTest() {    List<A> listA = new ArrayList<>();    listA.add(new A("a2", 1));    listA.add(new A("a3", 3));    listA.add(new A("a3", 2));    listA.add(new A("a1", 3));    System.out.println("原始:" + listA);    // 1.基于A的order升序排序    //办法一:list中的对象A实现Comparable接口,间接sort    listA.sort(Comparator.naturalOrder());    System.out.println("1.基于order升序——办法1:" + listA);    //办法二:若A没有实现Comparable接口,应用Comparator.comparing    listA.sort(Comparator.comparing(A::getOrder));    System.out.println("1.基于order升序——办法2:" + listA);    // 2.基于A的order及name的升序排序    List<A> result1 = listA.stream().sorted(Comparator.comparing(A::getOrder).thenComparing(A::getName)).collect(Collectors.toList());    System.out.println("2.基于A的order及name的升序排序——办法2扩大:" + result1);    // 3.基于A的order及name的降序排序    List<A> result2 = listA.stream().sorted(Comparator.comparing(A::getOrder).thenComparing(A::getName).reversed()).collect(Collectors.toList());    System.out.println("3.基于A的order及name的降序排序——办法2扩大:" + result2);    // 4.基于A的order升序以及name的降序排序    Comparator<A> comparatorName = (a1, a2) -> -a1.getName().compareTo(a2.getName());    listA.sort(Comparator.comparing(A::getOrder).thenComparing(comparatorName));    System.out.println("4.基于A的order升序以及name的降序排序——办法2扩大:" + listA);    //办法三:自定义排序    Comparator<A> comparator = (a1, a2) -> {        if (a1.getOrder().equals(a2.getOrder())) {            return -a1.getName().compareTo(a2.getName());        }        return a1.getOrder().compareTo(a2.getOrder());    };    listA.sort(comparator);    System.out.println("4.基于order升序及name降序——办法3:" + listA);}

运行后果:

原始:[order=1 name=a2, order=3 name=a3, order=2 name=a3, order=3 name=a1]1.基于order升序——办法1:[order=1 name=a2, order=2 name=a3, order=3 name=a3, order=3 name=a1]1.基于order升序——办法2:[order=1 name=a2, order=2 name=a3, order=3 name=a3, order=3 name=a1]2.基于A的order及name的升序排序——办法2扩大:[order=1 name=a2, order=2 name=a3, order=3 name=a1, order=3 name=a3]3.基于A的order及name的降序排序——办法2扩大:[order=3 name=a3, order=3 name=a1, order=2 name=a3, order=1 name=a2]4.基于A的order升序以及name的降序排序——办法2扩大:[order=1 name=a2, order=2 name=a3, order=3 name=a3, order=3 name=a1]4.基于order升序及name降序——办法3:[order=1 name=a2, order=2 name=a3, order=3 name=a3, order=3 name=a1]

2 Map排序

2.1 根本数据类型的排序

罕用的存储数据的map构造是HashMap,它有着高效的增删改查效率,然而HashMap无奈记录数据的程序,因而排序时罕用linkedHashMap存储有序数据。

HashMap、LinkedHashMap的具体介绍参考:
1、https://blog.csdn.net/qq_2876...
2、https://www.cnblogs.com/coder...
@Testpublic void test(){    Map<String, Double> map = new HashMap<>();    map.put("b", 0.08);    map.put("a", 0.1);    map.put("c", 0.02);    map.put("d", 0.91);    System.out.println("原始:"+map);    Map<String, Double> result = new LinkedHashMap<>();    map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));    System.out.println("按key升序排:"+result);    Map<String, Double> result2 = new LinkedHashMap<>();    map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEachOrdered(e -> result2.put(e.getKey(), e.getValue()));    System.out.println("按value升序排:"+result2);}

运行后果:

原始:{a=0.1, b=0.08, c=0.02, d=0.91}按key升序排:{a=0.1, b=0.08, c=0.02, d=0.91}按value升序排:{c=0.02, b=0.08, a=0.1, d=0.91}

逆序能够在comparingByKey或comparingByValue后增加reversed,将排序办法封装如下:

/* * 基于value排序 * @param  isReverse 示意是否逆序排 * @return  */public <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, boolean isReverse) {    Map<K, V> result = new LinkedHashMap<>();    if (isReverse) {        map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue().reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));    } else {        map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));    }    return result;}/* * 基于key排序 * @param  isReverse 示意是否逆序排 * @return */public <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isReverse) {    Map<K, V> result = new LinkedHashMap<>();    if (isReverse) {        map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));    } else {        map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));    }    return result;}

除了HashMap和LinkedHashMap之外,还有一种不须要额定的排序操作,数据存储时就是有序的构造,称之为TreeMap。

TreeMap的具体介绍参考:
1、https://blog.csdn.net/chenssy...
2、https://www.liaoxuefeng.com/w...

其应用办法如下:

@Testpublic void treeMapTest(){    TreeMap<String,Double> map = new TreeMap<>();    map.put("b", 0.08);    map.put("a", 0.1);    map.put("c", 0.02);    System.out.println("默认按key正序:"+map);    TreeMap<String,Double> map2 = new TreeMap<>(new Comparator<String>() {        @Override        public int compare(String o1, String o2) {            return -o1.compareTo(o2);        }    });    map2.put("b", 0.08);    map2.put("a", 0.1);    map2.put("c", 0.02);    System.out.println("自定义按key逆序:"+map2);}
留神:TreeMap仅反对对key排序,如需对value排序,则须要转换成list之后再sort,不再赘述。

2.2 JavaBean类型的排序

常见的场景是:map的value存储的JavaBean,须要依照JavaBean中的字段排序。
比方依照A的order升序及name的降序排序,代码如下:

@Testpublic void objectTest(){    Map<String, A> map = new HashMap<>();    map.put("b", new A("a2", 1));    map.put("a", new A("a3", 3));    map.put("c", new A("a3", 2));    map.put("d", new A("a1", 3));    Map<String, A> result = new LinkedHashMap<>();    Comparator<Map.Entry<String, A>> comparator = (c1, c2) -> {        A a1=c1.getValue();        A a2=c2.getValue();        if (a1.getOrder().equals(a2.getOrder())) {            return -a1.getName().compareTo(a2.getName());        }        return a1.getOrder().compareTo(a2.getOrder());    };    map.entrySet().stream().sorted(comparator).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));    System.out.println("按value升序排:"+result);}

运行后果:

依照value中的order升序及name的降序排序{b=order=1 name=a2, c=order=2 name=a3, a=order=3 name=a3, d=order=3 name=a1}