<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          高德面試:為什么Map不能插入null?

          共 4342字,需瀏覽 9分鐘

           ·

          2024-06-06 08:08

          面試題大全:www.javacn.site

          在 Java 中,Map 是屬于 java.util 包下的一個(gè)接口(interface),所以說(shuō)“為什么 Map 不能插入 null?”這個(gè)問(wèn)題本身問(wèn)的不嚴(yán)謹(jǐn)。Map 部分類關(guān)系圖如下:所以,這里面試官其實(shí)想問(wèn)的是:為什么 ConcurrentHashMap 不能插入 null?

          1.HashMap和ConcurrentHashMap的區(qū)別

          HashMap 和 ConcurrentHashMap 在對(duì)待 null 的態(tài)度上是不同的,在 Java 中,HashMap 是允許 key 和 value 值都為 null 的,如下代碼所示:

          HashMap<String, Object> map = new HashMap();
          map.put(nullnull);
          if (map.containsKey(null)) {
              System.out.println("存在 null");
          else {
              System.out.println("不存在 null");
          }

          以上程序的執(zhí)行結(jié)果如下:

          存在 null

          從上述結(jié)果可以看出,HashMap 是允許  key 和 value 值都為 null 的。

          但 ConcurrentHashMap 就不同了,它不但 key 不能為 null,而且 value 也不能為 null,如以下代碼所示:

          ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap();
          concurrentHashMap.put(null"javacn.site");
          System.out.println(concurrentHashMap.get(null));

          在運(yùn)行以上程序時(shí)就會(huì)報(bào)錯(cuò),如下圖所示:當(dāng)然,當(dāng)你為 ConcurrentHashMap 的 value 值設(shè)置 null 時(shí)也會(huì)報(bào)錯(cuò),如下代碼所示:

          String key = "www.avacn.site";
          ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap();
          concurrentHashMap.put(key, null);
          System.out.println(concurrentHashMap.get(key));

          在運(yùn)行以上程序時(shí)就會(huì)報(bào)錯(cuò),如下圖所示:因此,我們可以得出結(jié)論:

          1. 在 HashMap 中,key 和 value 值都可以為 null。
          2. 在 ConcurrentHashMap 中,key 或者是 value 值都不能為 null。

          2.為什么不能插入null?

          如果我們查看 ConcurrentHashMap 的源碼,就能發(fā)現(xiàn)為什么 ConcurrentHashMap 不能插入 null 了,以下是 ConcurrentHashMap 添加元素時(shí)的部分核心源碼:

          // 添加 key 和 value
          public V put(K key, V value) {
              return putVal(key, value, false);
          }
          final V putVal(K key, V value, boolean onlyIfAbsent) {
              // 如果 key 或 value 為 null 的話直接拋出空指針異常
              if (key == null || value == nullthrow new NullPointerException();
              int hash = spread(key.hashCode());
              int binCount = 0;
              // 忽略其他代碼......
          }

          從上述 ConcurrentHashMap 添加元素的第一行源碼就可以看出,當(dāng) key 或 value 為 null 時(shí),會(huì)直接拋出空指針異常,這就是 ConcurrentHashMap 之所以不能插入 null 的根本原因了,因?yàn)樵创a就是這樣設(shè)計(jì)的。

          3.更深層次的原因

          那么問(wèn)題來(lái)了,為什么 ConcurrentHashMap 的實(shí)現(xiàn)源碼中,不允許為 key 或者是 value 設(shè)置 null 呢?

          這就要從 ConcurrentHashMap 的使用場(chǎng)景說(shuō)起了,在 Java 中,ConcurrentHashMap 是用于并發(fā)環(huán)境中執(zhí)行的線程安全的容器,而 HashMap 是用于單線程環(huán)境下執(zhí)行的非線程安全的容器,而并發(fā)環(huán)境下的運(yùn)行更復(fù)雜,如果我們?cè)试S ConcurrentHashMap 的 key 或者是 value 為 null 的情況下,就會(huì)存在經(jīng)典的“二義性問(wèn)題”

          3.1 什么是二義性問(wèn)題?

          所謂的二義性問(wèn)題指的是代碼或表達(dá)式存在多種理解或解釋,導(dǎo)致程序的含義不明確或模糊。

          以 ConcurrentHashMap 不允許為 null 的二義性問(wèn)題來(lái)說(shuō),null 其實(shí)有以下兩層含義:

          1. 這個(gè)值本身設(shè)置的是 null,null 在這里表示的是一種具體的“null”值狀態(tài)。
          2. null 還表示“沒(méi)有”的意思,因?yàn)闆](méi)有設(shè)置,所以啥也沒(méi)有。

          所以,如果 ConcurrentHashMap 允許插入 null 值,那么就會(huì)存在二義性問(wèn)題。

          那就有同學(xué)會(huì)問(wèn)了,為什么 HashMap 允許插入 null,它就不怕有二義性問(wèn)題嗎?

          3.1 可證偽的HashMap

          HashMap 之所以不怕二義性問(wèn)題的原因是,HashMap 的設(shè)計(jì)是給單線程使用的,而單線程下的二義性問(wèn)題是能被證明真?zhèn)蔚模砸簿筒淮嬖诙x性問(wèn)題了(能被證明的問(wèn)題就不是二義性問(wèn)題)

          例如,當(dāng)我們給 HashMap 的 key 設(shè)置為 null 時(shí),我們可以通過(guò) hashMap.containsKey(key) 的方法來(lái)區(qū)分這個(gè) null 值到底是存入的 null?還是壓根不存在的 null?這樣二義性問(wèn)題就得到了解決,所以 HashMap 的二義性問(wèn)題可被證明真?zhèn)危跃筒慌露x性問(wèn)題,因此也就可以給 key 或者 value 設(shè)置 null 了。

          3.2 不可證偽的ConcurrentHashMap

          而 ConcurrentHashMap 就不一樣了,因?yàn)?ConcurrentHashMap 是設(shè)計(jì)在多線程下使用的,而多線程下的二義性問(wèn)題是不能被證明真?zhèn)蔚模远x性問(wèn)題是真實(shí)存在的

          因?yàn)樵谀阍谧C明二義性問(wèn)題的同時(shí),可能會(huì)有另一個(gè)線程影響你的執(zhí)行結(jié)果,所以它的二義性問(wèn)題就一直存在。

          例如,當(dāng) ConcurrentHashMap 未設(shè)置 key 為 null 時(shí),會(huì)有這樣一個(gè)場(chǎng)景,當(dāng)一個(gè)線程 A 調(diào)用了 concurrentHashMap.containsKey(key),我們期望返回的結(jié)果是 false,但在我們調(diào)用 concurrentHashMap.containsKey(key) 之后,未返回結(jié)果之前,線程 B 又調(diào)用了 concurrentHashMap.put(key,null) 存入了 null 值,那么線程 A 最終返回的結(jié)果就是 true 了,這個(gè)結(jié)果和我們之前預(yù)想的 false 完全不一樣,這就是不能被證偽的二義性問(wèn)題。

          所以說(shuō),多線程的執(zhí)行比較復(fù)雜,在多線程下 null 的二義性問(wèn)題是不能被證明真?zhèn)蔚模ㄒ驗(yàn)樵谝粋€(gè)線程執(zhí)行驗(yàn)證時(shí),可能會(huì)有另一個(gè)線程改動(dòng)結(jié)果,造成結(jié)果不準(zhǔn)確),所以 ConcurrentHashMap 為了避免這個(gè)二義性問(wèn)題,所以就在源碼中禁用了 null 值作為 key 或 value。

          課后思考

          除了 ConcurrentHashMap 之后,還有哪些容器不允許使用 null 作為 key 或者 value 呢?

          特殊說(shuō)明

          以上內(nèi)容來(lái)自我的《Java 面試突擊訓(xùn)練營(yíng)》,這門課程是有著 14 年工作經(jīng)驗(yàn)(前 360 開發(fā)工程師),9 年面試官經(jīng)驗(yàn)的我,花費(fèi) 4 年時(shí)間打磨完成的一門視頻面試課

          整個(gè)課程從 Java 基礎(chǔ)到微服務(wù) Spring Cloud、從實(shí)際開發(fā)問(wèn)題到場(chǎng)景題應(yīng)有盡有,包含模塊如下:訓(xùn)練營(yíng)系統(tǒng)的帶領(lǐng)大家把 Java 常見的面試題過(guò)一遍,遇到一個(gè)問(wèn)題,把這個(gè)問(wèn)題相關(guān)的內(nèi)容都給大家講明白,并且視頻支持永久觀看和一直更新。并且面試訓(xùn)練營(yíng)還提供 9 大就業(yè)服務(wù)。

          上完訓(xùn)練營(yíng)的課程之后,基本可以應(yīng)對(duì)目前市面上絕大部分公司的面試了,幫你快速找到高薪工作,加我微信咨詢:GG_Stone【備注:訓(xùn)練營(yíng)】


          瀏覽 241
          1點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          1點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美a精品 | 欧美另类色图 | 久操爱| 国产精品拍拍视频 | の夫婦交換中中文字幕 |