如何对各种Map进行排序

2020-07-25  本文已影响0人  文景大大

在通常的排序场景中,我们都是使用List或者是Set来承载各个元素,然后使用Collections工具类来进行排序,这块排序主要就是通过实现Comparable接口或者是新建一个Comparator比较器来实现的,比较简单,可以参考Java中的Comparable和Comparator

然而有的时候,我们承载元素的集合类是Map,这种情况下怎么实现对Map中元素的排序呢?或者是否有更好的数据结构可以解决这个问题呢?

一、Map的分类

    public static void main(String[] args) {
        HashMap<String,Integer> myHashMap = new HashMap();
        myHashMap.put("zIndex",12);
        myHashMap.put("mIndex",12);
        myHashMap.put("qIndex",12);
        myHashMap.put("fIndex",12);
        myHashMap.put("bIndex",12);

        // 遍历输出,判断是否是按照key升序保存的
        Set<String> mySet = myHashMap.keySet();
        for(String currentKey : mySet){
            log.info("key:{}-value:{}", currentKey, myHashMap.get(currentKey));
        }
    }

输出结果如下,可以看到确实是无序的:

key:bIndex-value:12
key:qIndex-value:12
key:fIndex-value:12
key:mIndex-value:12
key:zIndex-value:12
public static void main(String[] args) {
        LinkedHashMap<String,Integer> myLinkedHashMap = new LinkedHashMap();
        myLinkedHashMap.put("zIndex",12);
        myLinkedHashMap.put("mIndex",12);
        myLinkedHashMap.put("qIndex",12);
        myLinkedHashMap.put("fIndex",12);
        myLinkedHashMap.put("bIndex",12);

        // 遍历输出,判断是否是按照key升序保存的
        Set<String> mySet = myLinkedHashMap.keySet();
        for(String currentKey : mySet){
            log.info("key:{}-value:{}", currentKey, myLinkedHashMap.get(currentKey));
        }
    }

输出结果如下,发现和存储的顺序是一致的:

key:zIndex-value:12
key:mIndex-value:12
key:qIndex-value:12
key:fIndex-value:12
key:bIndex-value:12
public static void main(String[] args) {
        TreeMap<String,Integer> myTreeMap = new TreeMap();
        myTreeMap.put("zIndex",12);
        myTreeMap.put("mIndex",12);
        myTreeMap.put("qIndex",12);
        myTreeMap.put("fIndex",12);
        myTreeMap.put("bIndex",12);

        // 遍历输出,判断是否是按照key升序保存的
        Set<String> mySet = myTreeMap.keySet();
        for(String currentKey : mySet){
            log.info("key:{}-value:{}", currentKey, myTreeMap.get(currentKey));
        }
    }

输出结果如下,默认是按照key升序存储的:

key:bIndex-value:12
key:fIndex-value:12
key:mIndex-value:12
key:qIndex-value:12
key:zIndex-value:12

二、各种Map实现排序

2.1 HashMap的排序

因为HashMap中存放元素是无序的,所以肯定不能在HashMap数据结构中进行排序,我们只能将元素放到List中,利用List进行排序。

    public static void main(String[] args) {
        Map<String, String> fruitMap = new HashMap<>();
        fruitMap.put("orange", "china");
        fruitMap.put("banana", "usa");
        fruitMap.put("apple", "canada");
        fruitMap.put("grape", "england");

        List<Map.Entry<String, String>> fruitList = new ArrayList<>(fruitMap.entrySet());
        Collections.sort(fruitList, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                // 按照水果产地的字母升序排列
                return o1.getValue().compareTo(o2.getValue());
            }
        });

        for (Map.Entry<String, String> fruit : fruitList) {
            log.info("{} from {}", fruit.getKey(), fruit.getValue());
        }
    }

可以看到,想要对HashMap进行排序,还是比较麻烦的,不但要借助额外的存储空间List,排序的方法看上去也不简洁。

这时,可以推荐使用commons-lang3中pair数据结构进行元素的承载和排序。

    public static void main(String[] args) {
        // MutablePair是Pair的实现类,一个Pair只能存放一个键值对
        Pair<String,String> orangePair = new MutablePair("orange", "china");
        Pair<String,String> bananaPair = new MutablePair("banana", "usa");
        Pair<String,String> applePair = new MutablePair("apple", "canada");
        Pair<String,String> grapePair = new MutablePair("grape", "england");

        List<Pair<String,String>> fruitList = new ArrayList<>();
        fruitList.add(orangePair);
        fruitList.add(bananaPair);
        fruitList.add(applePair);
        fruitList.add(grapePair);

        fruitList.sort(new Comparator<Pair<String, String>>() {
            // 按照水果产地的字母升序排列
            @Override
            public int compare(Pair<String, String> o1, Pair<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
        });

        for (Map.Entry<String, String> fruit : fruitList) {
            log.info("{} from {}", fruit.getKey(), fruit.getValue());
        }
    }

Map一次性可以存储多个键值对,Pair只能存放一个键值对,由于Map在初始化空间的时候默认是16,所以当我们只需要保存一个键值对的时候,Pair更加省空间,速度也更加快。

2.2 TreeMap的排序

TreeMap在存储元素的时候,默认会按照key进行升序排列后存储,所以在默认情况下就是有序的。

    public static void main(String[] args) {
        Map<String, String> fruitMap = new TreeMap<>();
        // 按照水果名称的字母升序排列
        fruitMap.put("orange", "china");
        fruitMap.put("banana", "usa");
        fruitMap.put("apple", "canada");
        fruitMap.put("grape", "england");

        // TreeMap默认已经按照key升序排列了
        Iterator<String> iterator = fruitMap.keySet().iterator();
        while(iterator.hasNext()){
            String currentFruit = iterator.next();
            log.info("{} from {}", currentFruit, fruitMap.get(currentFruit));
        }
    }

如果我们想实现自定义的按照键的排序方式,可以在创建TreeMap的时候就实例化比较器。

        Map<String, String> fruitMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 自定义如何按照键进行排序——按照水果名称的字母升序排列
                return o2.compareTo(o1);
            }
        });

如上只是按照键进行排序,如果我们想按照value进行排序呢?我们还是得回到HashMap的排序方式路子上去。

上一篇 下一篇

猜你喜欢

热点阅读