一、Map简介

在讲解Map排序之前,我们先来稍微了解下map。map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。其中这四者的区别如下(简单介绍):

1、HashMap:我们最常用的Map,它根据key的HashCode 值来存储数据,根据key可以直接获取它的Value,同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null。非同步的。

2、TreeMap: 能够把它保存的记录根据key排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。

3、Hashtable: 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

4、LinkedHashMap: 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。


简单总结为:

map:无序
Treemap:默认是升序(以key作为标准)
Linkedhashmap:默认是插入数据时的顺序



二、Comparator接口


(A)、方法


int compare(T o1,T o2)



(B)、说明


比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
在前面的描述中,符号 sgn(expression) 表示 signum 数学函数,根据 expression 的值为负数、0 还是正数,该函数分别返回 -1、0 或 1。


简单来说就是,Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1,小于、等于或者大于o2分别返回负整数、0或者正整数。


(C)、参数:o1 - 要比较的第一个对象。
o2 - 要比较的第二个对象。


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


三、示例


1、按键排序


TreeMap<K,V>既可满足此类需求,向其构造方法 TreeMap(Comparator<? super K> comparator)  传入我们自定义的比较器即可实现按键排序。


/**
     * 按Key进行排序
     */
    @Test
    public void TestSort1(){
        Map<String, String> resultMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String str1, String str2) {
                return str1.compareTo(str2);
            }
        });
        resultMap.put("1", "kfc");
        resultMap.put("2", "wnba");
        resultMap.put("3", "nba");
        resultMap.put("4", "cba");
        for (Map.Entry<String, String> entry : resultMap.entrySet()) {
            System.out.println(entry.getKey() + " " + entry.getValue());
        }
    }




2、按值排序


Map本身按值排序是很有意义的,很多场合下都会遇到类似需求,可以认为其值是定义的某种规则或者权重。

原理:将待排序Map中的所有元素置于一个列表中,接着使用Collections的一个静态方法 sort(List<T> list, Comparator<? super T> c) 
来排序列表,同样是用比较器定义比较规则。排序后的列表中的元素再依次装入Map,为了肯定的保证Map中元素与排序后的List中的元素的顺序一致,使用了LinkedHashMap数据类型。


/**
     * 按Value进行排序
     */
    @Test
    public void TestSort2(){
        Map<String, String> resultMap = new TreeMap<String, String>();
        resultMap.put("kfc", "1");
        resultMap.put("wnba", "2");
        resultMap.put("nba", "6");
        resultMap.put("cba", "4");
        resultMap.put("eba", "5");
        resultMap.put("ebe", "0");
        Map<String, String> sortedMap = new LinkedHashMap<String, String>();
        List<Map.Entry<String, String>> entryList = new ArrayList<Map.Entry<String, String>>(
                resultMap.entrySet());

        Collections.sort(entryList, new Comparator<Entry<String, String>>() {
            @Override
            public int compare(Entry<String, String> o1, Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
        });

        Iterator<Map.Entry<String, String>> iter = entryList.iterator();
        Map.Entry<String, String> tmpEntry = null;
        while (iter.hasNext()) {
            tmpEntry = iter.next();
            sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());
        }

        for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
            System.out.println(entry.getKey() + " " + entry.getValue());
        }
    }



3.随机排序



/**
     * 三种排序
     * 1.升序排列
     * 2.降序排序
     * 3.随机排序
     */
    @Test
    public void TestSort3() {
        //默认的TreeMap升序排列
        TreeMap<Integer, Integer> map1 = new TreeMap<Integer, Integer>();
        
        //降序排序
        TreeMap<Integer, Integer> map2 = new TreeMap<Integer, Integer>(new Comparator<Integer>() {
            /*
            * int compare(Object o1, Object o2) 返回一个基本类型的整型,
            * 返回负数表示:o1 小于o2,
            * 返回0 表示:o1和o2相等,
            * 返回正数表示:o1大于o2。
            */
            public int compare(Integer o1, Integer o2) {
                return  o2 - o1;
            }
        });

        //随机排序
        TreeMap<Integer, Integer> map3 = new TreeMap<Integer, Integer>(new Comparator<Integer>() {
            /*
            * int compare(Object o1, Object o2) 返回一个基本类型的整型,
            * 返回负数表示:o1 小于o2,
            * 返回0 表示:o1和o2相等,
            * 返回正数表示:o1大于o2。
            */
            public int compare(Integer a, Integer b) {
                int randomOne = (int) (Math.random() * 10);
                int randomTwo = (int) (Math.random() * 10);
                return randomOne - randomTwo;
            }
        });

        map2.put(1, 2);
        map2.put(2, 4);
        map2.put(2, 4);
        map2.put(7, 1);
        map2.put(5, 2);
        System.out.println("Map2降序排列=" + map2);

        map1.put(1, 2);
        map1.put(2, 4);
        map1.put(7, 1);
        map1.put(5, 2);
        map1.put(5, 2);
        System.out.println("map1升序排序=" + map1);

        map3.put(1, 2);
        map3.put(2, 4);
        map3.put(7, 1);
        map3.put(5, 2);
        map3.put(9, 2);
        map3.put(11, 2);
        map3.put(11, 2);
        System.out.println("map3随机排序=" + map3);
    }



4.Map转成List使用Collections.shuffle()随机排序


/**
     * Map转List 随机排序
     * @throws IOException
     */
    @Test
    public void TestSort4() throws IOException {
        Map<String, Object> unsortMap = new HashMap<>();
        unsortMap.put("z", 10);
        unsortMap.put("b", 5);
        unsortMap.put("a", 6);
        unsortMap.put("c", 20);
        unsortMap.put("d", 1);
        unsortMap.put("e", 7);
        unsortMap.put("y", 8);
        unsortMap.put("n", 99);
        unsortMap.put("g", 50);
        unsortMap.put("m", 2);
        unsortMap.put("f", 9);
        List<String> list = new LinkedList(unsortMap.keySet());
        //随机排序
        Collections.shuffle(list);
        Map<String,Object> result = new HashMap<String,Object>();
        for (int i = 0; i < list.size(); i++) {
            String jsonString = list.get(i);
            result.put(jsonString, unsortMap.get(jsonString));
        }
        for (Map.Entry<String, Object> entry : result.entrySet()) {
            System.out.println(entry.getKey() + " " + entry.getValue());
        }
    }