1. 程式人生 > >JAVA Map 升序|降序|隨機|去重排序

JAVA Map 升序|降序|隨機|去重排序

一、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());
        }
    }