日韩性视频-久久久蜜桃-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| 高潮毛片又色又爽免费 | 91av在线视频播放 | 91视频精品| 免费在线观看成人av | 天天躁日日躁aaaxxⅹ | 国产成人av一区二区 | 欧美一二三区 | 四虎黄色片 | 激情天天 | 欧美动态色图 | 秋霞综合网 | 国产精品-色哟哟 | 国产4区 | 国产精品3 | 国语播放老妇呻吟对白 | 成人黄色免费网 | 好吊视频一区二区 | 亚洲自拍av在线 | 欧美午夜精品久久久久久浪潮 | 日韩精品第一 | 黄色一级图片 | 中文字幕一区二区三区乱码在线 | 丰满秘书被猛烈进入高清播放在 | 一级特黄a大片免费 | 99视频在线免费观看 | 国产精品日日夜夜 | 中文字幕在线观 | 人人爽人人澡 | 日本高清在线一区 | 精品久久91 | 日韩中文视频 | 毛片一级视频 | 久久黄色视屏 | 欧美成人免费播放 | 久草香蕉视频 | 蜜桃av鲁一鲁一鲁一鲁俄罗斯的 | 日本特黄一级片 | 中文字幕一区二区三区精华液 | av导航在线观看 | 爱豆国产剧免费观看大全剧集 | 91视频免费在线 | 特级淫片裸体免费看 | 动漫精品一区一码二码三码四码 | 日韩激情精品 | 毛片视频免费播放 | 爱逼综合网 | 亚洲一区二区三区日韩 | 在线免费看91 | 天天色综合天天 | 色网站在线看 | 综合狠狠| 琪琪色在线视频 | 性色av一区二区三区在线观看 | 欧美色图13p | 污污的网站在线观看 | 久久男人网 | 久久国产精品精品国产 | 国精品人妻无码一区二区三区喝尿 | 在线观看日批视频 | 富二代成人短视频 | 色屋在线 | 久久bb | 国产精品一区在线看 | 午夜伦理福利视频 | 亚洲av久久久噜噜噜熟女软件 | 91在线免费播放 | 欧美精品色 | 99久久久国产精品无码网爆 | 成人刺激视频 | 久久99精品久久久久久琪琪 | 日日摸日日添日日碰9学生露脸 | 国产精品一区二区在线看 | 亚洲av色区一区二区三区 | h在线播放 | 欧美日韩精品一区二区三区蜜桃 | 一区二区三区四区视频在线观看 | 欧美影院一区二区三区 | jzzijzzij亚洲成熟少妇 | www黄色com | 亚洲丝袜色图 | 久久久久久久久综合 | 久久久久久视 | 狠狠操在线播放 | 国产日韩欧美在线 | 在线看b| 欧美日韩国产一区二区 | 爽爽爽av | 国产真实乱偷精品视频 | 精品免费观看 | 日韩在线观看视频一区二区 | 黄毛片在线观看 |