zoukankan      html  css  js  c++  java
  • 关于List,Set,Map能否存储null

     

    本文源码为jdk1.8版本

    喵的,今天面试问这个卡壳了,明明我之前看了的,邀请面试的是你,拒绝我的也是你,你为什么那么熟练啊QAQ

        @Test
        public void testArrayList(){
            ArrayList<String> list = new ArrayList<>();
            list.add(null);
            list.add(null);
            Assert.assertEquals(2,list.size()); // success
        }
    
        @Test
        public void testLinkedList(){
            LinkedList<String> list = new LinkedList<>();
            list.add(null);
            list.add(null);
            Assert.assertEquals(2,list.size()); // success
        }
    

    首先是List,可以看到ArrayList可以存储多个null,ArrayList底层是数组,添加null并未对他的数据结构造成影响。LinkedList底层为双向链表,node.value = null也没有影响。


    @Test
        public void testHashMap(){
            HashMap<String,String> map = new HashMap<>();
            map.put(null,null);
            Assert.assertEquals(1,map.size()); //OK size = 1
    
            map.put(null,null);
            Assert.assertEquals(2,map.size()); //Error size = 1
        }
    
     @Test
        public void testTreeMap(){
            TreeMap<String,String> map = new TreeMap<>();
            map.put(null,null);
            Assert.assertEquals(1,map.size()); //Error NullPointException
            
        }
    

    关于Map,HashMap中最多只有一个key == null的节点,因为key相同时,后面的节点会替换之前相同key的节点,所以HashMap是可以添加key == null 的节点的,只不过只会存在一个,有兴趣的话可以去看源码(tips:源码真的眼花缭乱,可以尝试自己写上注释,更容易看懂,菜鸟的方法)put方法返回旧值。TreeMap的put方法会调用compareTo方法,对象为null时,会报空指针错。


        @Test
        public void testHashSet(){
            HashSet<String> set = new HashSet<>();
            set.add(null);
            Assert.assertEquals(1,set.size()); //OK size = 1
            set.add(null);
            Assert.assertEquals(2,set.size()); //Error size = 1
    
        }
    
        @Test
        public void testTreeSet(){
            TreeSet<String> set = new TreeSet<>();
            set.add(null); //Error NullPointException
        }
    

    最后是Set,HashSet底层是HashMap,所以它的put()如下,也只能有一个null。

        private static final Object PRESENT = new Object();
    
    
        public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }
    

    TreeSet的put()也是如此。

        public boolean add(E e) {
            return m.put(e, PRESENT)==null;
        }
    
    • 结果:
    • List都可以添加null元素
    • HashMap可以有1个key为null的元素,TreeMap不能有key为null的元素
      Set底层是Map
    • 所以HashSet可以有1个null的元素,TreeSet不能有key为null的元素。

    面试官,您看您还要我吗?

    续上:

    • Vector 底层是数组,所以不会管你元素的内容是什么,可以存储多个null
        @Test
        public void VectorTest(){
            Vector box = new Vector();
            box.add(null);
            box.add(null);
            Assert.assertEquals(2,box.size()); //ok
        }
    
        /**
        *此为Vector的add函数
        **/
        public synchronized boolean add(E e) {
            modCount++;
            ensureCapacityHelper(elementCount + 1);
            elementData[elementCount++] = e;
            return true;
        }
    
    • HashTable底层为散列表,无论是key为null,还是value为null,都会报错
        @Test
        public void HashTableTest(){
            Hashtable table = new Hashtable();
            //table.put(new Object(),null); //Exception
            //table.put(null,new Object()); //Exception
            //table.put(null,null); //Exception
            Assert.assertEquals(1,table.size());
        }
    
        //此为hashTable#put函数源码
       public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {   //value 需要判空,所以value不可为null
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();     //key需要拥有实例去调用hashCode方法,所以也不能为空
            int index = (hash & 0x7FFFFFFF) % tab.length;
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            for(; entry != null ; entry = entry.next) {
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
    
            addEntry(hash, key, value, index);
            return null;
        }
    
    

    至于为什么hashtable键和值都设计成不能为null,牛客网的一位大佬这样说到:

     

    以上。

  • 相关阅读:
    cocos2d-x 3.0 事件分发机制
    cocos2d-x Schedule详解
    OSG设置警告等级
    OSG四元数与欧拉角之间的转换
    编译OSG_FBX插件
    RakNet发送与接收数据
    RakNet基本教程
    IE不能上网,但是其他浏览器可以
    OSG计时器与时间戳
    添加OSG各种事件处理器
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/12722043.html
Copyright © 2011-2022 走看看