????????先說下功能需求,上傳聯(lián)系人,因為聯(lián)系人可能過多,不上傳聯(lián)系人頭像,只上傳聯(lián)系人姓名,號碼,但是UI上展示已經(jīng)上傳的聯(lián)系人的時候又需要展示頭像,這時候,只能是從服務(wù)器獲取到聯(lián)系人,然后去匹配本機(jī)的聯(lián)系人,找到頭像,然后展示。
????????有的同學(xué)說了,那簡單啊,兩層for循環(huán)嵌套下,找到本地的聯(lián)系人頭像展示就完事了,代碼大致是這種:

????????上面這種,的確沒有BUG,但卻是一種很爛的算法,復(fù)雜度達(dá)到了O(N2),如果別人聯(lián)系人非常多的情況下,這種寫法,效率會低到不行。這種時候我們就要考慮進(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)為其是同一個對象。這樣就可以以本地聯(lián)系人來覆蓋服務(wù)器拿到的聯(lián)系人,話不多說,上代碼:

? ? ? ? 然后我們就可以建立一個以Contact對象為KEY,Contact的頭像Uri為value的HashMap
1.把后臺獲取到的Contact全部放到hashmap里,此時value全為null,因為后臺根本沒有頭像地址
2.把本地獲取到的Contact全部放到hashmap里,value對應(yīng)為本地獲取到的頭像Uri,此時,如果姓名 號碼 都一致,后臺獲取的Contact對象與本地的Contact對象就會產(chǎn)生碰撞,碰撞之后HashMap會判斷兩個對象是否 equal,如果不equal,就把其插入到對應(yīng)散列位置的鏈表里,但是我們已經(jīng)覆蓋了equal方法,所以肯定是相等的,hashmap就會直接用新插入的值覆蓋掉之前的值。此時我們就得到了一個帶有本地聯(lián)系人頭像URI的hashmap.
3.遍歷服務(wù)器獲取到的聯(lián)系人,一一去hashmap取到頭像URI,塞入到服務(wù)器獲取到的聯(lián)系人對象里。大功告成,上代碼:

總結(jié):代碼很簡單,只要思路對了,實現(xiàn)起來很快。PS:之前獲取本地聯(lián)系人的時候,悶頭網(wǎng)上找一段拿來復(fù)制粘貼,結(jié)果就進(jìn)了坑,復(fù)制了一份雙層循環(huán)的查詢語句,后來仔細(xì)看的時候大概是先查詢到所有的contactId然后通過contactId去aw_contacts表中讀取raw_contact_id,再用raw_contact_id到data表讀取所有信息,導(dǎo)致測試的時候,大概多于1000個聯(lián)系人的時候,APP直接ANR,蠻尷尬。復(fù)制代碼需謹(jǐn)慎,哈哈。