日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通过一个实际案例,彻底搞懂 HashMap!

發(fā)布時間:2025/3/21 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通过一个实际案例,彻底搞懂 HashMap! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我知道大家都很熟悉hashmap,并且有事沒事都會new一個,但是hashmap的一些特性大家都是看了忘,忘了再記,今天這個例子可以幫助大家很好的記住。

場景

用戶提交一張試卷答案到服務(wù)端,post報文可精簡為

[{"question\_id":"100001","answer":"A"}, {"question\_id":"100002","answer":"A"}, {"question\_id":"100003","answer":"A"}, {"question\_id":"100004","answer":"A"}]

提交地址采用restful風(fēng)格

http://localhost:8080/exam/{試卷id}/answer

那么如何比對客戶端傳過來的題目就是這張試卷里的呢,假設(shè)用戶偽造了試卷怎么辦?

正常解決思路

1、得到試卷所有題目id的list

2、2層for循環(huán)比對題號和答案

3、判定分?jǐn)?shù)

大概代碼如下

//讀取post題目 for?(MexamTestpaperQuestion?mexamTestpaperQuestion?:?mexamTestpaperQuestions)?{//通過考試試卷讀取題目選項對象MexamQuestionOption?questionOption?=?mexamQuestionDao.findById(mexamTestpaperQuestion.getQuestionId());map1.put("questionid",?mexamTestpaperQuestion.getQuestionId());map1.put("answer",?mexamQuestionDao.findById(mexamTestpaperQuestion.getQuestionId()).getAnswer());questionAnswerList.add(map1);//將每題分add到一個List }//遍歷試卷內(nèi)所有題目 for?(Map<String,?Object>?stringObjectMap?:?list)?{//生成每題結(jié)果對象mexamAnswerInfo?=?new?MexamAnswerInfo();mexamAnswerInfo.setAnswerId(answerId);mexamAnswerInfo.setId(id);mexamAnswerInfo.setQuestionId(questionid);mexamAnswerInfo.setResult(anwser);for?(Map<String,?Object>?objectMap?:?questionAnswerList)?{if?(objectMap.get("questionid").equals(questionid))?{//比較答案if?(anwser.equals(objectMap.get("answer")))?{totalScore?+=?questionOption.getScore();mexamAnswerInfo.setIsfalse(true);}?else?{mexamAnswerInfo.setIsfalse(false);}}}mexamAnswerInfoDao.addEntity(mexamAnswerInfo); }

使用普通的2層for循環(huán)解決了這個問題,一層是數(shù)據(jù)庫里的題目,一層是用戶提交的題目,這時候bug就會暴露出來,假設(shè)用戶偽造了1萬道題目或更多,服務(wù)端運算量將增大很多。

利用hashmap來解決

首先,看看它的定義

基于哈希表的 Map 接口的實現(xiàn)。此實現(xiàn)提供所有可選的映射操作,并允許使用 null 值和 null 鍵。(除了不同步和允許使用 null 之外,HashMap 類與 Hashtable?大致相同。)此類不保證映射的順序,特別是它不保證該順序恒久不變。

主要看HashMap?k-v均支持空值,我們何不將用戶提交了答案add到一個HashMap里,其中題目id作為key,答案作為value,而且HashMap的key支持以字母開頭。

我們只需要for循環(huán)試卷所有題目,然后通過這個map.put("題目id")就能得到答案,然后比較答案即可,因為HashMap的key是基于hashcode的形式存儲的,所以在程序中該方案效率很高。

思路:

1、將提交答案以questionid為key,answer為value加入一個hashmap

2、for循環(huán)實體列表,直接比對答案

3、判分

代碼如下:

//拿到用戶提交的數(shù)據(jù) Map<String,?String>?resultMap?=?new?HashMap<>();JSONArray?questions?=?JSON.parseArray(params.get("questions").toString()); for?(int?size?=?questions.size();?size?>?0;?size--)?{JSONObject?question?=?(JSONObject)?questions.get(size?-?1);resultMap.put(question.getString("questionid"),?question.getString("answer")); } //拿到試卷下的所有試題 List<MexamTestpaperQuestion>?mexamTestpaperQuestions?=?mexamTestpaperQuestionDao.findBy(map); int?totalScore?=?0; for?(MexamTestpaperQuestion?mexamTestpaperQuestion?:?mexamTestpaperQuestions)?{MexamQuestionOption?questionOption?=?mexamQuestionDao.findById(mexamTestpaperQuestion.getQuestionId());MexamAnswerInfo?mexamAnswerInfo?=?new?MexamAnswerInfo();mexamAnswerInfo.setAnswerId(answerId);mexamAnswerInfo.setId(id);mexamAnswerInfo.setQuestionId(questionOption.getId());mexamAnswerInfo.setResult(resultMap.get(questionOption.getId()));//拿到試卷的id作為resultMap的key去查,能查到就有這個題目,然后比對answer,進行存儲if?(questionOption.getAnswer().equals(resultMap.get(questionOption.getId())))?{mexamAnswerInfo.setIsfalse(true);totalScore?+=?questionOption.getScore();}?else?{mexamAnswerInfo.setIsfalse(false);}mexamAnswerInfoDao.addEntity(mexamAnswerInfo); }

分析HashMap??

先看看文檔

大概翻譯為如下幾點:

1、實現(xiàn)Map ,可克隆,可序列化

2、基于哈希表的Map接口實現(xiàn)。

3、此實現(xiàn)提供所有可選的映射操作,并允許 空值和空鍵。(HashMap?類大致相當(dāng)于Hashtable,除非它是不同步的,并且允許null)。這個類不能保證Map的順序; 特別是不能保證訂單在一段時間內(nèi)保持不變。

4、這個實現(xiàn)為基本操作(get和put)提供了恒定時間的性能,假設(shè)散列函數(shù)在這些存儲桶之間正確分散元素。集合視圖的迭代需要與HashMap實例的“容量” (桶數(shù))及其大小(鍵值映射數(shù))成正比 。因此,如果迭代性能很重要,不要將初始容量設(shè)置得太高(或負(fù)載因子太低)是非常重要的。

5、HashMap的一個實例有兩個影響其性能的參數(shù):初始容量和負(fù)載因子。容量是在哈希表中桶的數(shù)量,和初始容量是簡單地在創(chuàng)建哈希表中的時間的能力。該負(fù)載系數(shù)是的哈希表是如何充分允許獲得之前它的容量自動增加的措施。當(dāng)在散列表中的條目的數(shù)量超過了負(fù)載因數(shù)和電流容量的乘積,哈希表被重新散列(即,內(nèi)部數(shù)據(jù)結(jié)構(gòu)被重建),使得哈希表具有桶的大約兩倍。

那么put邏輯是怎么樣的呢?

HashMap的key在put時,并不需要挨個使用equals比較,那樣時間復(fù)雜度O(n),也就說 HashMap 內(nèi)有多少元素就需要循環(huán)多少次。

而HashMap是將key轉(zhuǎn)為hashcode,關(guān)于hashcode的確可能存在多個string相同的hashcode,但是最終HashMap還會比較一次bucketIndex。bucketIndex是HashMap存儲k-v的位置,時間復(fù)雜度只有O(1)。

源碼??

?

/***?Associates?the?specified?value?with?the?specified?key?in?this?map.*?If?the?map?previously?contained?a?mapping?for?the?key,?the?old*?value?is?replaced.**?@param?key?key?with?which?the?specified?value?is?to?be?associated*?@param?value?value?to?be?associated?with?the?specified?key*?@return?the?previous?value?associated?with?<tt>key</tt>,?or*?????????<tt>null</tt>?if?there?was?no?mapping?for?<tt>key</tt>.*?????????(A?<tt>null</tt>?return?can?also?indicate?that?the?map*?????????previously?associated?<tt>null</tt>?with?<tt>key</tt>.)*/ public?V?put(K?key,?V?value)?{//?以key的哈希碼作為key??return?putVal(hash(key),?key,?value,?false,?true); }/***?Implements?Map.put?and?related?methods**?@param?hash?hash?for?key*?@param?key?the?key*?@param?value?the?value?to?put*?@param?onlyIfAbsent?if?true,?don't?change?existing?value*?@param?evict?if?false,?the?table?is?in?creation?mode.*?@return?previous?value,?or?null?if?none*/ final?V?putVal(int?hash,?K?key,?V?value,?boolean?onlyIfAbsent,boolean?evict)?{Node<K,V>[]?tab;?Node<K,V>?p;?int?n,?i;//?處理key為null,HashMap允許key和value為null?if?((tab?=?table)?==?null?||?(n?=?tab.length)?==?0)n?=?(tab?=?resize()).length;if?((p?=?tab[i?=?(n?-?1)?&?hash])?==?null)tab[i]?=?newNode(hash,?key,?value,?null);else?{Node<K,V>?e;?K?k;if?(p.hash?==?hash?&&((k?=?p.key)?==?key?||?(key?!=?null?&&?key.equals(k))))e?=?p;else?if?(p?instanceof?TreeNode)//以樹形結(jié)構(gòu)存儲e?=?((TreeNode<K,V>)p).putTreeVal(this,?tab,?hash,?key,?value);else?{//以鏈表形式存儲for?(int?binCount?=?0;?;?++binCount)?{if?((e?=?p.next)?==?null)?{p.next?=?newNode(hash,?key,?value,?null);if?(binCount?>=?TREEIFY_THRESHOLD?-?1)?//?-1?for?1sttreeifyBin(tab,?hash);break;}if?(e.hash?==?hash?&&((k?=?e.key)?==?key?||?(key?!=?null?&&?key.equals(k))))break;p?=?e;}}//如果是key已存在則修改舊值,并返回舊值if?(e?!=?null)?{?//?existing?mapping?for?keyV?oldValue?=?e.value;if?(!onlyIfAbsent?||?oldValue?==?null)e.value?=?value;afterNodeAccess(e);return?oldValue;}}++modCount;if?(++size?>?threshold)resize();//如果key不存在,則執(zhí)行插入操作,返回null。afterNodeInsertion(evict);return?null; }

put方法分兩種情況:bucket是以鏈表形式存儲的還是以樹形結(jié)構(gòu)存儲的。如果是key已存在則修改舊值,并返回舊值。如果key不存在,則執(zhí)行插入操作,返回null。put操作,當(dāng)發(fā)生碰撞時,如果是使用鏈表處理沖突,則執(zhí)行的尾插法。

put操作的大概流程:

1、通過hash值得到所在bucket的下標(biāo),如果為null,表示沒有發(fā)生碰撞,則直接put。

2、如果發(fā)生了碰撞,則解決發(fā)生碰撞的實現(xiàn)方式:鏈表還是樹。

3、如果能夠找到該key的結(jié)點,則執(zhí)行更新操作。

4、如果沒有找到該key的結(jié)點,則執(zhí)行插入操作,需要對modCount++。

5、在執(zhí)行插入操作之后,如果size超過了threshold,這要擴容執(zhí)行resize()。

作者:邵磊
juejin.im/post/59bc601ff265da0652708abd??

總結(jié)

以上是生活随笔為你收集整理的通过一个实际案例,彻底搞懂 HashMap!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 古代黄色片 | av中文字幕网 | 亚洲啪啪网 | 奇米四色在线观看 | 蜜臀av色欲a片无码精品一区 | 操综合| 亚洲在线视频观看 | 精品在线观看一区 | 久草资源在线视频 | 亚洲AV成人无码精品久久盆瓶 | 91操视频| www.白虎 | 影音先锋中文字幕在线播放 | 国产成人在线播放视频 | japanese国产打屁股网站 | 麻豆传媒网| 亚洲最大黄色 | 日韩成人免费观看 | 欧美老女人bb | 成人亚洲精品 | 51福利视频 | 国产精品无码一本二本三本色 | 蜜桃视频一区二区在线观看 | 小镇姑娘国语版在线观看免费 | 国产一区欧美 | 国产最新在线观看 | 美女扒开尿口给男人捅 | 精品中文字幕在线播放 | 精品国精品国产自在久不卡 | 国产精品福利小视频 | 精品影视一区二区 | 少妇色| 国模无码视频一区二区三区 | av在线手机观看 | 东凛在线观看 | 欧美午夜性春猛交 | 黄色专区 | 8050午夜一级毛片久久亚洲欧 | 成人欧美一区二区三区黑人免费 | 国产一区二区在线不卡 | 精品乱码一区二区三区 | 国产欧美精品久久 | 极品久久久久久 | 日本在线视频免费观看 | 成人香蕉视频在线观看 | 国产日韩视频在线观看 | 免费黄色在线 | 麻豆网站在线看 | 日韩精品视频在线看 | 免费三级网站 | 超碰凹凸| 九九超碰 | 亚洲 欧美 日韩 综合 | 国产又猛又黄又爽 | 日本中文字幕视频在线 | 国产一毛片| 亚洲一区人妻 | 黑白配高清国语在线观看 | 国产在线色视频 | 国产二区精品 | 国产电影一区二区三区 | 亚洲成人播放器 | 牛牛影视一区二区三区 | 在线观看国产黄色 | 天天曰天天干 | 欧洲精品码一区二区三区免费看 | 欧美全黄| 98精品视频| 亚洲欧洲成人精品久久一码二码 | 67194成人在线观看 | 美女露出粉嫩尿囗让男人桶 | 2019国产精品视频 | 亚洲第一免费网站 | 免费啪啪小视频 | 亚洲无人区码一码二码三码的含义 | 丰满岳乱妇一区二区 | 国产18在线观看 | 蜜桃传媒一区二区亚洲av | 欧美影视一区二区三区 | 熟女少妇一区二区三区 | 亚洲欧美一二三 | 成年人www | 欧美一区免费 | 久久久久久久久久国产精品 | 干干操操| 久久久久久国产精品一区 | 亚洲视频免费播放 | 91社区在线播放 | 波多野吉衣久久 | 成年人的毛片 | 久久久久中文字幕亚洲精品 | 亚洲毛片在线 | 欧美日韩99 | 蜜臀一区二区三区精品免费视频 | 亚洲人xxx日本人18 | 欧美日一区二区 | 色噜噜综合 | 免费污片软件 | 黑人玩弄人妻一区二 |