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

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


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

public V put(K key, V value) {

       Entry<K,V> 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<K,V> parent;

       // split comparator and comparable paths

       Comparator<? super K> 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<? super K> k = (Comparable<? super K>) 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<K,V> e = new Entry<>(key, value, parent);

       if (cmp < 0)

           parent.left = e;

       else

           parent.right = e;

       fixAfterInsertion(e);

       size++;

       modCount++;

       return null;

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值