TreeMap中是否能存储多个键为null的键值对

对于存储进TreeMap及TreeSet中的元素,要求元素自身具有比较性或者在创建集合时传入一个比较器对象。当调用TreeMap.put(key,value)时,如果root为空,也就是集合中没有元素时,不管key值是否为null,TreeMap都创建一个节点并将该节点作为树根节点存入集合中。当第二次存入key为null的键值对时,此时如果集合自身不带比较器,那么调用元素自身的compareTo()方法,即key.compareTo()方法,此时必然产生NullPointerException异常。例如,当创建一个存储键和值都是String类型,但自身不带比较器的TreeMap对象时,即TreeMap tm= new TreeMap();两次调用tm.put(null,”aaa”)时,第一次能顺利存入,因为TreeMap为空,直接创建一个根节点并将元素存入,但是第二次传入时,由于集合自身不带比较器,因此调用String.compareTo(String str)方法,必然产生空指针异常。

TreeMap中是否能存储多个键为null的键值对_第1张图片

但是当集合自身带有比较器对象时,调用的是比较器Comparator.compare(K key,K k),此时是否能正常存入完全取决于比较器。因此,TreeMap中能否存入多个键值为null的键值对取决于集合自带比较器。下面是TreeMap.put(K key,V value)源码分析。

public V put(K key, V value) {

       Entry t = root;

//如果根节点为空,也就是集合中没有元素,直接创建一个Entry节点并存入集合中,并将该节点作为root

       if (t == null) {

           compare(key, key); // type (and possibly null) check

 

           root = new Entry<>(key, value, null);

           size = 1;

           modCount++;

           return null;

       }

//如果集合自身带有比较器对象,优先使用集合自带的比较器,调用比较器的compare方法,在树中找一个合适位置并记录它的父亲节点

       int cmp;

       Entry parent;

       // split comparator and comparable paths

       Comparator cpr = comparator;

       if (cpr != null) {

           do {

                parent = t;

                cmp = cpr.compare(key, t.key);

                if (cmp < 0)

                    t = t.left;

                else if (cmp > 0)

                    t = t.right;

                else

                    return t.setValue(value);

           } while (t != null);

       }

       else {

//如果使用元素自身的compareTo方法,则key必须非空,只要为空,就产生空指针异常

           if (key == null)

                throw newNullPointerException();

//在树中找到一个合适位置,并记录它的父亲节点

           Comparable k = (Comparable) key;

           do {

                parent = t;

                cmp = k.compareTo(t.key);

                if (cmp < 0)

                    t = t.left;

                else if (cmp > 0)

                    t = t.right;

                else

                    return t.setValue(value);

           } while (t != null);

       }

       Entry e = new Entry<>(key, value, parent);

       if (cmp < 0)

           parent.left = e;

       else

           parent.right = e;

       fixAfterInsertion(e);

       size++;

       modCount++;

       return null;

    }

你可能感兴趣的:(java)