关于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,牛客网的一位大佬这样说到:


以上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Java集合类可用于存储数量不等的对象,并可以实现常用的数据结构如栈,队列等,Java集合还可以用于保存具有映射关...
    小徐andorid阅读 2,100评论 0 13
  • 集合 集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的...
    手打小黑板阅读 396评论 0 0
  • 原文地址 Java集合 Java集合框架:是一种工具类,就像是一个容器可以存储任意数量的具有共同属性的对象。 Ja...
    gyl_coder阅读 1,042评论 0 8
  • 集合相关 List跟Set的区别两个接口都继承Collection,区别list有序且可以添加多个null元素,也...
    DustMoon阅读 1,120评论 0 4
  • 集合类框架的介绍: ![Java 集合类框架](https://upload-images.jianshu.io/...
    LynnGuo阅读 805评论 0 1

友情链接更多精彩内容