前言
這道題目網上到處都是,但是好多都沒有講清楚,然后大家又相互轉載,錯誤泛濫,現在我來完善這道題目。
題目:每一個ip訪問百度,其ip地址都會被記錄到后台日志文件中,假設一天的訪問日志有100G,求出一天中訪問百度次數最多的ip地址,可以使用的內存大小是1G。
分析
- 首先解決大文件問題,也就是如何處理100G的一個大文件,這個通常的解決方法就是將大文件分解成許多小文件。我們可以通過對IP地址求hash然后對1024取模將一個100G的大文件分解成1024個小文件(file0,file1......file1023),注意這里的1024個文件並不是平均分的,也就是每個文件大小並不是(100G/1204)。當然我們考慮的時候可以假設文件是平均分的,那么每個文件大小為100M,這樣一個100M的文件是可以全部讀入大小為1G內存中。這樣就解決了第一個文件太大不能一次讀入內存的問題。
- 考慮到ip地址是32為,那么總共有2^32=4G種可能出現的ip地址,每個ip地址出現的次數不確定,這個具體是由100G大文件決定的。對每個小文件進行處理,我們知道前面每個文件中的ip是通過hash(ip)%1024。這樣相當於將2^32=4G種ip地址進行了分段,每個文件中可能出現的ip最大范圍是4G/1024=4M。創建一個hashmap,讀取小文件中的每個ip地址,判斷hashmap中是否有這個ip,如果沒有,這往haspmap中插入一個<ip,1>的鍵值對,即hashmap.put(ip,1);如果haspmap中已經存在了這個ip,那么求出這個ip所對應的值count=haspmap.get(ip),然后往修改這個ip所對應的value,使其數量增加1,即hashmap.set(ip,count+1)。
- 當我們求出每個文件中出現次數最大的ip地址以后,我們在比較這1024個文件中的那個ip出現次數最大
偽代碼實例
Mark for future reference hash(IP)%N get many small files int max = 0; String maxip = null; for each file Hashmap hashmap; String IP = readIP(file); if(hashmap.has(IP)) { int cnt = hashmap.get(IP); hashmap.set(IP, cnt+1); if(cnt+1 > max) { max = cnt+1; maxip = IP; } } else hashmap.put(IP, 1);