????????先說下功能需求,上傳聯(lián)系人鞠苟,因?yàn)槁?lián)系人可能過多乞榨,不上傳聯(lián)系人頭像,只上傳聯(lián)系人姓名当娱,號碼吃既,但是UI上展示已經(jīng)上傳的聯(lián)系人的時(shí)候又需要展示頭像,這時(shí)候跨细,只能是從服務(wù)器獲取到聯(lián)系人鹦倚,然后去匹配本機(jī)的聯(lián)系人,找到頭像冀惭,然后展示震叙。
????????有的同學(xué)說了,那簡單啊散休,兩層for循環(huán)嵌套下媒楼,找到本地的聯(lián)系人頭像展示就完事了,代碼大致是這種:
????????上面這種戚丸,的確沒有BUG划址,但卻是一種很爛的算法,復(fù)雜度達(dá)到了O(N2)昏滴,如果別人聯(lián)系人非常多的情況下猴鲫,這種寫法,效率會(huì)低到不行谣殊。這種時(shí)候我們就要考慮進(jìn)行算法優(yōu)化拂共,經(jīng)過思考,選擇利用散列來將復(fù)雜度從 N2 降低到 N姻几,散列的話宜狐,讀取的復(fù)雜度是常量階(如果不了解散列數(shù)據(jù)結(jié)構(gòu)的同學(xué)可以自行去學(xué)習(xí)一把),在這種需求下蛇捌,對于Java已經(jīng)封裝好的散列結(jié)構(gòu)我認(rèn)為HashMap最適合抚恒。
? ? ? ? 思路就是,首先络拌,讓后臺拿到的Contact對象與本地拿到的Contact對象在 姓名 與 號碼一致的情況下 hashcode一致俭驮,這樣才能產(chǎn)生碰撞(對象放到散列數(shù)組里的位置是其hashCode值與散列大小決定的),然后就是覆蓋equals方法,當(dāng) 姓名 和 號碼一致混萝,就認(rèn)為其是同一個(gè)對象遗遵。這樣就可以以本地聯(lián)系人來覆蓋服務(wù)器拿到的聯(lián)系人,話不多說逸嘀,上代碼:
? ? ? ? 然后我們就可以建立一個(gè)以Contact對象為KEY车要,Contact的頭像Uri為value的HashMap
1.把后臺獲取到的Contact全部放到hashmap里,此時(shí)value全為null崭倘,因?yàn)楹笈_根本沒有頭像地址
2.把本地獲取到的Contact全部放到hashmap里翼岁,value對應(yīng)為本地獲取到的頭像Uri,此時(shí)司光,如果姓名 號碼 都一致琅坡,后臺獲取的Contact對象與本地的Contact對象就會(huì)產(chǎn)生碰撞,碰撞之后HashMap會(huì)判斷兩個(gè)對象是否 equal飘庄,如果不equal脑蠕,就把其插入到對應(yīng)散列位置的鏈表里,但是我們已經(jīng)覆蓋了equal方法跪削,所以肯定是相等的,hashmap就會(huì)直接用新插入的值覆蓋掉之前的值迂求。此時(shí)我們就得到了一個(gè)帶有本地聯(lián)系人頭像URI的hashmap.
3.遍歷服務(wù)器獲取到的聯(lián)系人碾盐,一一去hashmap取到頭像URI,塞入到服務(wù)器獲取到的聯(lián)系人對象里揩局。大功告成毫玖,上代碼:
總結(jié):代碼很簡單,只要思路對了凌盯,實(shí)現(xiàn)起來很快付枫。PS:之前獲取本地聯(lián)系人的時(shí)候,悶頭網(wǎng)上找一段拿來復(fù)制粘貼驰怎,結(jié)果就進(jìn)了坑阐滩,復(fù)制了一份雙層循環(huán)的查詢語句,后來仔細(xì)看的時(shí)候大概是先查詢到所有的contactId然后通過contactId去aw_contacts表中讀取raw_contact_id县忌,再用raw_contact_id到data表讀取所有信息掂榔,導(dǎo)致測試的時(shí)候,大概多于1000個(gè)聯(lián)系人的時(shí)候症杏,APP直接ANR装获,蠻尷尬。復(fù)制代碼需謹(jǐn)慎厉颤,哈哈穴豫。