1. 程式人生 > >一道面試題看 HashMap 的儲存方式

一道面試題看 HashMap 的儲存方式

我們公司招人喜歡問演算法題和一些基礎知識。今天我們一個面試官在面試候選人之前在辦公室對我們說他準備問一個這樣的問題:

在 HashMap 中存放的一系列鍵值對,其中鍵為某個我們自定義的型別。放入 HashMap 後,我們在外部把某一個 key 的屬性進行更改,然後我們再用這個 key 從 HashMap 裡取出元素,這時候 HashMap 會返回什麼?

我們辦公室幾個人答案都不一致,有的說返回null,有的說能正常返回value。但不論答案是什麼都沒有確鑿的理由。我覺得這個問題挺有意思的,就寫了程式碼測試。結果是返回null。需要說明的是我們自定義的類重寫了 hashCode 方法。我想這個結果還是有點意外的,因為我們知道 HashMap 存放的是引用型別,我們在外面把 key 更新了,那也就是說 HashMap 裡面的 key 也更新了,也就是這個 key 的 hashCode 返回值也會發生變化。這個時候 key 的 hashCode 和 HashMap 對於元素的 hashCode 肯定一樣,equals也肯定返回true,因為本來就是同一個物件,那為什麼不能返回正確的值呢?

先來看看一段測試程式碼:

先解釋一下測試程式碼做到事。定義了一個person類,就兩個屬性。重寫了 hashCode 方法,還有一套geter和seter,沒什麼特別。測試類裡面先建立了三個person物件作為 key 。列印各個 key 的 hashCode 值。然後三個元素放到 HashMap ,接著更新其中一個 key 的name屬性,最後去取這個 key 的value。

Java
1234567891011121314151617181920212223242526272829303132 publicclassPerson{privateStringname;privateintheight;@OverridepublicinthashCode(){System.out.println(this.name+": HashCode() invoked!");returnthis.name.hashCode()+this.height;}publicStringgetName(){return
name;}publicvoidsetName(Stringname){this.name=name;}publicintgetHeight(){returnheight;}publicvoidsetHeight(intheight){this.height=height;}@OverridepublicStringtoString(){return"Name:"+this.name+"; height:"+this.height;}}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;publicclassHashmapTest{publicstaticvoidmain(String[]args){Map<Person,String>testMap=newHashMap<Person,String>();Person p1=newPerson();p1.setName("Jakie");p1.setHeight(165);Person p2=newPerson();p2.setName("Jerry");p2.setHeight(175);Person p3=newPerson();p3.setName("Torres");p3.setHeight(160);System.out.println(p1+";hashcode:"+p1.hashCode()+"\n");System.out.println(p2+";hashcode:"+p2.hashCode()+"\n");System.out.println(p3+";hashcode:"+p3.hashCode()+"\n");System.out.println("************************");System.out.println("putting objectinto map");testMap.put(p1,"p1");testMap.put(p2,"p2");testMap.put(p3,"p3");System.out.println("************************");p2.setName("Jerry isnow kelly");System.out.println("P2 hashcode after update:");System.out.println(p2+";hashcode:"+p2.hashCode()+"\n");System.out.println("**************************");System.out.println("Hash Code of elements inHashMap");for(Entry<Person,String>entry:testMap.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue()+":"+entry.getKey().hashCode());System.out.println();if(entry.getKey().getName().equals("Jakie")){System.out.println("Jakie inmap isthe original jakie"+(entry.getKey()==p1));}elseif(entry.getKey().getName().equals("Jerry isnow kelly")){System.out.println("Jerry isnow kelly inmap isthe original Jerry"+(entry.getKey()==p2));}}System.out.println("**********************");Stringp=testMap.get(p2);System.out.println("FinalResult:"+p);}}

輸出:

Java
123456789101112131415161718192021222324 Name:Jakie;height:165;hashcode:71336629Name:Jerry;height:175;hashcode:71462829Name:Torres;height:160;hashcode:-1784098647************************putting objectinto map************************P2 hashcode after update:Name:Jerry isnow kelly;height:175;hashcode:-711681872**************************Hash Code of elements inHashMapName:Jerry isnow kelly;height:175:p2:-711681872Jerry isnow kelly inmap isthe original Jerry trueName:Jakie;height:165:p1:71336629Jakie inmap isthe original jakie trueName:Torres;height:160:p3:-1784098647**********************FinalResult:null

從輸出我們可以知道, key 更新後 hashCode 確實更新了。而且 HashMap 裡面的物件就是我們原來的物件。最後的結果是null。

我們來看一下 HashMap 的get方法原始碼:

1234567

相關推薦

一道試題 HashMap儲存方式

我們公司招人喜歡問演算法題和一些基礎知識。今天我們一個面試官在面試候選人之前在辦公室對我們說他準備問一個這樣的問題: 在 HashMap 中存放的一系列鍵值對,其中鍵為某個我們自定義的型別。放入 HashMap 後,我們在外部把某一個 key 的屬性進行更改,然後我

Python之美[從菜鳥到高手]--讀"一道試題 HashMap儲存方式"的聯想

在 HashMap 中存放的一系列鍵值對,其中鍵為某個我們自定義的型別。放入 HashMap 後,我們在外部把某一個 key 的屬性進行更改,然後我們再用這個 key 從 HashMap 裡取出元素,這時候 HashMap 會返回什麼?如何面試者直接答“這要看自定義型別的ha

一道試題ES6箭頭函式

前幾天頭條面試碰到了這樣一道面試題,讓我寫出每行程式碼的執行結果: var f = x => x; f(1); //return 1 var f = x => {x}; f(1); //function(x)={x}; var f = x =

今天做到一道試題:Android中程序的通訊方式

由於android系統中應用程式之間不能共享記憶體。因此,在不同應用程式之間互動資料(跨程序通訊)就稍微麻煩一些。在android SDK中提供了4種用於跨程序通訊的方式。這4種方式正好對應於android系統中4種應用程式元件:Activity、Content Provider、Broadcast和Se

一道試題來認識java類加載時機與過程【轉】

包含 布局 hello 印象 大致 周期 default () itl 說明:本文的內容是看了《深入理解Java虛擬機:JVM高級特性與最佳實踐》後為加印象和理解,便記錄了重要的內容。 1 開門見山 以前曾經看到過一個java的面試題,當時覺得此題很簡單,可是自己

一道試題引發的數據庫行列轉換實踐

聚合函數 列數 index 所有 then 重復 一個 mysq 場景 問題場景 最近有個朋友去面試,問了我一道面試題。題目如下,在形如下面的數據庫表score中,找出每門成績(grade)都大於等於80分的學生姓名。 -------------------------

經典試題:js繼承方式

deep 今天 typeof extend fun col const 繼承 uber 上一篇講解了構造函數的繼承方式,今天來講非構造函數的繼承模式。 一、object()方法 json格式的發明人Douglas Crockford,提出了一個object()函數,可以做到

Java基礎中的一道試題

override ktr void ati star 打印 str @override ... 這個是我以前的一道面試題: public class MyThread extends Thread { @Override public void run() { tr

關於Java類加載雙親委派機制的思考(附一道試題

另類 app 類庫 .com 任務 發現 clas context 表示 預定義類加載器和雙親委派機制 JVM預定義的三種類型類加載器: 啟動(Bootstrap)類加載器:是用本地代碼實現的類裝入器,它負責將 <Java_Runtime_Home>/l

跟濤哥一起學嵌入式 第04集:一道試題,測出你的C語言功底

inux 臨時 新增 取數據 max 指針 code 個人主頁 ctu 大家好,我是濤哥,歡迎閱讀《跟濤哥一起學嵌入式》第04集,今天聊聊面試題。 嵌入式C語言面試題中,大家經常會看到宏定義的考題。比如:定義一個宏,求兩個數中的最大數。別小看這個考題,雖然簡單,但是它卻陷阱

java試題之----HashMap常見面試題總結

使用 這一 hashtable 此刻 獲取 重要性 microsoft ria 取值 “你用過HashMap嗎?” “什麽是HashMap?你為什麽用到它?” 幾乎每個人都會回答“是的”,然後回答HashMap的一些特性,譬如HashMap可以接受null鍵值和值,而Has

有關java類、對象初始化的話題,從一道試題切入

() 深入理解java 補充 [] base sna 字體 都是 spa 最近在整理東西時,剛好碰到以前看的一道有關java類、對象初始化相關題目,覺得答案並不是非常好(記憶點比較差,不是很連貫)。加上剛好復習完類加載全過程的五個階段(加載-驗證-準備-解析-初始化),所以

一道試題的分析

com var 沒有 優先級 alt 面試題 http console 圖片 題目: console.log(a); var a=1; console.log(a); function a(){console.log(2);} console.log(a); var a=

一道試題的解析

原題 function Foo(){ getName = function(){ alert(1) } return this } Foo.getName = function(){ alert(2) } Foo.prototype.getName = function(){

機器人學-一道試題

\(求解過程如下:​\) \(化簡得到:\) \(y''=100*cos(y)-100*sin(y)\) ① \(x''=g=9.81\) ② \(對①式進行積分得到如下結果:​\) \(1/2*y'*y'=100*sin(y)+100*cos(y)+C\) ③ \(由於y(0)=y'(0)=0,

一道試題之關於自定義Json解析器

最近在群裡裡面有哥們說在面試的時候,要求上機寫一個簡單的Json解析器,看到這個題目的時候,心裡慌得一比,因為感覺有些力不從心,不知道從哪裡下手,所以趕緊查了一下Gson原始碼,看看有什麼啟示沒有。當然,這篇扯淡並不是介紹Gson原始碼,而是想自定義一個簡單的Json解析器,來熟悉一下J

一道試題(C語言)

題:輸入一個數,列出所有加和等於該數的式子。 分析: 以 6 為例: 從上面的分析就比較容易找到規律了。 C語言程式碼: 1 #include <stdio.h> 2 3 int main() 4 { 5 int n; // 輸入的數 6

Google的一道試題的推廣(扔雞蛋不破的層數,2個,3個,n個雞蛋呢)

1題目描述 google面試題:幾年前的Google的面試題在論壇炒得很火,今年又被人人網當作面試題了,題目如下:“有一個100層高的大廈,你手中有兩個相同的雞蛋。從這個大廈的某一層扔下雞蛋就會碎,用你手中的這兩個雞蛋,找出一個最優的策略,來得知那個臨界層面。” 人人網面試題:原題來自:2014人人網研發

一道試題:說說程序和執行緒的區別

在理解這些概念之前首選要對併發有一定的感性認識,如果伺服器同一時間內只能服務於一個客戶端,其他客戶端都再那裡傻等的話,可見其效能的低下估計會被客戶罵出翔來,因此併發程式設計應運而生,併發是網路程式設計中必須考慮的問題。實現併發的方式有多種:比如多程序、多執行緒、IO多路複用。 在理解這些概念

一道試題引發的“血案”

前言 es6之前,js的作用域只有兩種,全域性作用域和函式作用域,沒有像C和java那樣的塊級作用域,於是對於學了C或者java這類語言的然後學習js的同學來說,會遇到很多坑。js的這個特性導致了程式碼的可閱讀性、維護性和容錯性都不太好。因此es6可以用let來申明變數,這