List,Set,Map能否存储null

List

常用的List有ArrayList和LinkedList。

    @Test
    public void testList(){
        List arrayList = new ArrayList();
        arrayList.add(null);
        arrayList.add(null);
        System.out.println(arrayList.size());

        List linkedList = new LinkedList();
        linkedList.add(null);
        linkedList.add(null);
        System.out.println(linkedList.size());
    }

打印结果:

2
2

由于ArrayList底层是数组,添加null并未对他的数据结构造成影响。LinkedList底层为双向链表,node.value = null也没有影响。因此,它们都可以存储多个null。

Map

常用的Map有HashMap和TreeMap。针对Map,由于存储的是键值对,我们主要关注key能否为null。

    @Test
    public void testMap() {
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put(null, "a");
        hashMap.put(null, "b");
        System.out.println(hashMap.size());

        Map<String, String> treeMap = new TreeMap<>();
        treeMap.put(null, "a");
        treeMap.put(null, "b");
        System.out.println(treeMap.size());
    }

打印结果:

HashMap中最多只有一个key == null的节点,因为key相同时,后面的节点会替换之前相同key的节点,所以HashMap是可以添加key == null 的节点的,只不过只会存在一个,put方法返回旧值。TreeMap的put方法会调用compareTo方法,对象为null时,会报空指针。

针对HashMap存null节点,这里可以再多说一点。HashMap 允许插入键为 null 的键值对,但是因为无法调用 null 的 hashCode() 方法,也就无法确定该键值对的桶下标,只能通过强制指定一个桶下标来存放。

在jdk1.8版本下,处理如下:

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

也就是说,key为null时,HashMap 使用第 0 个桶存放键为 null 的键值对。这也解释了HashMap为什么只能存放一个key为null的节点。

Set

常用的Set有HashSet和TreeSet。

    @Test
    public void testSet(){
        Set<String> hashSet = new HashSet();
        hashSet.add(null);
        hashSet.add(null);
        System.out.println(hashSet.size());

        Set<String> treeSet = new TreeSet<>();
        treeSet.add(null);
        treeSet.add(null);
        System.out.println(treeSet.size());
    }

打印结果:

HashSet底层是HashMap,add方法调用的是HashMap的put方法,也只能有一个null。

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

TreeSet底层是TreeMap,add方法调用的是TreeMap的put方法,会报空指针异常。

总结:

  • List都可以添加null元素
  • HashMap可以有1个key为null的元素,TreeMap不能有key为null的元素
    所以HashSet底层是HashMap,可以有1个null的元素,TreeSet底层是TreeMap,不能有key为null的元素。

除了上述介绍的之外,集合家族还有很多其它的类型。如下面两张图。

【手动分割图片】

【手动分割图片】

这里补充三种集合类型。

【1】Vector 底层是数组,所以不会管你元素的内容是什么,可以存储多个null

【2】HashTable无论是key为null,还是value为null,都会报错。

Hashtable都是支持并发的,这样会有一个问题,map.get(key) 的返回结果是null,那么是因为不存在对应的key是null呢,还是key对应的value就是null。

      HashMap是非并发的,可以通过contains(key)来做这个判断。而支持并发的Map在调用m.contains(key)和m.get(key),m可能已经不同了。

      HashTable是很早的一个类了,JDK已经并不推荐使用。在并发场景下,更建议使用ConcrrentHashMap

【3】ConcurrentHashmap,同Hashtable。

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

架构帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值