java之map集合存放null值的问题

 更新时间:2023年11月01日 10:12:10   作者:马丁半只瞄  
这篇文章主要介绍了java之map集合存放null值的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

java map集合存放null值问题

今天接到阿里的电话面试提到了一个问题是关于HashTable、HashMap的区别

集合类keyvaluesuper说明
HashTable不能为null不能为nullDictionary线程安全
ConcurrentHashMap不能为null不能为nullAbstractMap线程局部安全
TreeMap不能为null可以为nullAbstractMap线程不安全
HashMap可以为null可以为nullAbstractMap线程不安全

以此为记~

java 集合能否加入null值

项目场景

剑指 Offer 09. 用两个栈实现队列

	public int deleteHead() {
        while(s2.isEmpty()){
        //注意这里,我直接判断第二个栈空就加入第一个栈中的元素,没有判断第一个栈是否为空(当时想的是第一个栈为空不会加入元素或者抛出异常)
            s2.offerFirst(s1.pollFirst());
        }
        if(s1.isEmpty()&&s2.isEmpty()){
            return -1;
        }
        return s2.pollFirst();
    }

问题描述

写力扣题时出现了这个问题,原代码在上面。

原因分析

尝试输出了下,发现总是返回空值,

1)认为输入栈(s1)为空会抛出异常,但是忘记了offer和poll针对异常不做处理,push和pop会抛出异常

2)跟着debug发现输出栈(s2)元素永远不为空,因为加入了s1的null,这就有意思了,java中有的集合可以加入null,有的不可以,所以顺便总结一下。

解决方案

	public int deleteHead() {
        while(s1.isEmpty()&&s2.isEmpty()){
            return -1;
        }
        if(s2.isEmpty()){
            while(!s1.isEmpty()){
                s2.offerFirst(s1.pollFirst());
            }
        }
        return s2.pollFirst();
    }

1.List

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

	@Test
    public void testArrayList() {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(null);
        list.add(null);
        System.out.println(list.size());//2
    }

    @Test
    public void testLinkedList() {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(null);
        list.add(null);
        System.out.println(list.size());//2
    }

2.Set

Set底层是map,所以和map一样

3.Map

关于Map,HashMap中最多只有一个key == null的节点,因为key相同时,后面的节点会替换之前相同key的节点,所以HashMap是可以添加key == null 的节点的,只不过只会存在一个put方法返回旧值。

TreeMap的put方法会调用compareTo方法,对象为null时,会报空指针错。

	@Test
    public void testHashMap() {
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(null, null);
        map.put(null, null);
        System.out.println(map.size());//1
    }
    @Test
    public void testTreeMap() {
        TreeMap<Integer, Integer> map = new TreeMap<>();
        map.put(null, null);
        System.out.println(map.size());//NullPointerException
    }

TreeMap源码

4.Vector

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;
    }

5.HashTable

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

6.ConcurrentHashMap

看上面那张图

总结

结果:

  • List都可以添加null元素
  • HashMap可以有1个key为null的元素,TreeMap不能key为null的元素
  • Set底层是Map,所以HashSet可以有1个null的元素,TreeSet不能有key为null的元素。
  • -线程安全的类key和value都不能是null

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java基础MAC系统下IDEA连接MYSQL数据库JDBC过程

    Java基础MAC系统下IDEA连接MYSQL数据库JDBC过程

    最近一直在学习web项目,当然也会涉及与数据库的连接这块,这里就总结一下在IDEA中如何进行MySQL数据库的连接,这里提一下我的电脑是MAC系统,使用的编码软件是IDEA,数据库是MySQL
    2021-09-09
  • 在Linux环境下搭建Java环境和部署Web项目

    在Linux环境下搭建Java环境和部署Web项目

    本文介绍了在Linux环境下搭建Java部署环境的步骤,包括使用虚拟机、WSL、云服务器等方法,重点讲解了使用云服务器(如阿里云)的详细步骤,包括购买服务器、连接服务器、配置远程登录、安装必要的软件包(如JDK和MySQL)以及部署Web项目
    2026-03-03
  • 快速排序算法在Java中的实现

    快速排序算法在Java中的实现

    这篇文章主要介绍了快速排序算法在Java中的实现,简单介绍了快速排序的实现原理,分享了两种实现代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • springboot自定义yml配置文件及其外部部署过程

    springboot自定义yml配置文件及其外部部署过程

    这篇文章主要介绍了springboot自定义yml配置文件及其外部部署过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java中使用Preconditions来检查传入参数介绍

    Java中使用Preconditions来检查传入参数介绍

    这篇文章主要介绍了Java中使用Preconditions来检查传入参数介绍,本文只是作为一个简单的用法介绍,需要的朋友可以参考下
    2015-06-06
  • Spring中@Async注解实现异步调详解

    Spring中@Async注解实现异步调详解

    在本篇文章里小编给大家分享的是关于Spring中@Async注解实现异步调详解内容,需要的朋友们可以学习下。
    2020-04-04
  • Java枚举之EnumSet详解

    Java枚举之EnumSet详解

    这篇文章主要介绍了Java枚举之EnumSet详解,使用时进行与或运算,但是定义多了之后,会很乱、臃肿,编写容易出错,EnumSet可以实现类似的功能,且使用起来很简洁,需要的朋友可以参考下
    2023-12-12
  • springboot统一接口返回数据的实现

    springboot统一接口返回数据的实现

    这篇文章主要介绍了springboot统一接口返回数据的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Mybatis-plus多数据源配置的两种方式总结

    Mybatis-plus多数据源配置的两种方式总结

    这篇文章主要为大家详细介绍了Mybatis-plus中多数据源配置的两种方式,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-10-10
  • Java中JSON对象字段为null值的显示处理方法

    Java中JSON对象字段为null值的显示处理方法

    这篇文章主要给大家介绍了关于Java中JSON对象字段为null值的显示处理方法,最近开发过程中前端反应后台返回的json中包含null,不好处理,这里介绍下,需要的朋友可以参考下
    2023-08-08

最新评论