C/C++教程

TreeMap自定义compare后get永远返回null的问题

本文主要是介绍TreeMap自定义compare后get永远返回null的问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 问题描述
  • 问题跟踪
  • 修复代码
  • 其他思考

问题描述

今天有一个需求,需要根据map中的value进行排序,首先肯定就想到了TreeMap,于是实现了一个Comparator,代码如下:

    class ValueComparator implements Comparator<Character> {

        Map<Character, Integer> base;

        public ValueComparator(Map<Character, Integer> base) {
            this.base = base;
        }
        
        public int compare(Character a, Character b) {
            if (base.get(a) >= base.get(b)) {
                return -1;
            } else {
                return 1;
            }
        }
    }

奇怪的是,排序没有问题,可以当我使用treeMap.get()时,永远返回null。

问题跟踪

话不多说,直接debug,发现如下代码:

    final Entry<K,V> getEntry(Object key) {
        // Offload comparator-based version for sake of performance
        if (comparator != null)
            return getEntryUsingComparator(key);
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = k.compareTo(p.key);
            if (cmp < 0)
                p = p.left;
            else if (cmp > 0)
                p = p.right;
            else
                return p;
        }
        return null;
    }

原来treeMap和hashMap的get原理完全不同,hashMap会根据key的hash值找到对应的Node获取其中的value,而treeMap在有自定义Comparator的情况下,会使用自定义Comparator将所有的key和get中的key作比较,返回值为0的时候才会返回value。
由于我自定义的Comparator只有返回1和-1,所以永远得到的都是null。

修复代码

    class ValueComparator implements Comparator<Character> {

        Map<Character, Integer> base;

        public ValueComparator(Map<Character, Integer> base) {
            this.base = base;
        }

        public int compare(Character a, Character b) {
            if (base.get(a) == base.get(b)) {
                return 0;
            } else if (base.get(a) < base.get(b)){
                return 1;
            }
            return -1;
        }
    }

其他思考

由此可见,treeMap虽时候排序,但是get的效率相较于hashMap还是较低的,毕竟hashMap可以通过key的hash值直接定位到Node的位置,不考虑hash碰撞情况下,时间复杂度是O(1)。
而treeMap则是通过compare方法,比较大小来判断是否是当前的Entry,如果返回<0,往左边找,如果返回>0,往右边找,典型的二分查找,所以时间复杂度是O(log n),所以在没有排序需求的情况下,hashMap是大家做常用的Map。

这篇关于TreeMap自定义compare后get永远返回null的问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!