把访问P站次数最多的那个人才给我找出来?
如果我掌握了P站的所有访问日志数据(海量),我想找出某一天访问次数最多的那个IP,并看看到底是那个国家的小哥精力如此旺盛???
对于这种问题,说到底,就是一个“分与合”的思想。
我们需要从访问P站日志中,把具体某一天的所有IP取出来,再逐个写入到一个大文件中。值得一提的是,IP是32位的,那么就有2^32个IP,就算扣除特殊IP,在重复量小的情况下,一般来说,不能直接把这些数据放入到内存里面。
这里的话,我们需要采用hash映射的方法,比如取模1000,把这个大文件分割成1000个小文件,再去小文件中找出出现频率最大的IP,并记录其出现频次;最后,再从这1000个IP中找到出现频次最大的IP,这样便把一个看似不能解决的问题就给解决了。
具体操作:
-
对IP地址进行hash(IP)%1000求值,再把海量IP日志分别存储到1024个小文件中;
-
分别对每一个小文件,构建一个{k:IP ,v:频次}的map,并记录下当前小文件频次最多的IP;
-
对得到的这个1000个IP,进行常规排序,便能得到最大的IP
1、构造数据
生成1亿个IP地址,写入文件:
public void genIP(String fileName) throws Exception {
PrintWriter out = new PrintWriter(fileName);
String s;
Random r = new Random();
for (int i = 0; i < 100000000; i++) {
s = "159.227.";
s += r.nextInt(256) + "." + r.nextInt(256);
out.println(s);
}
if (out != null)
out.close();
}
2、分割文件
把这个大文件分割成1000个小文件,代码如下:
public void splitMiniFile(String fileName) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
PrintWriter[] out = new PrintWriter[1000];
for (int i = 0; i < 1000; i++) {
out[i] = new PrintWriter(fileName + i);
}
String ip = null;
while ((ip = reader.readLine()) != null) {
ip = reader.readLine();
int fileNum = ip.hashCode() % 1000;
fileNum = (fileNum >= 0 ? fileNum : fileNum + 1000);
out[fileNum].println(ip);
}
for (int i = 0; i < 1000; i++) {
out[i].close();
}
reader.close();
}
3、统计IP
对每个小文件里面的ip进行统计,并获取最大频次的ip,代码如下:
public Map.Entry<String, Integer> statisIps(String fileName) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
HashMap<String, Integer> map = new HashMap<String, Integer>();
String ip = null;
while ((ip = reader.readLine()) != null) {
if (map.containsKey(ip)) {
map.put(ip, map.get(ip) + 1);
} else
map.put(ip, 1);
}
Map.Entry<String, Integer> maxEntry = null;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (maxEntry == null || entry.getValue() > maxEntry.getValue()) {
maxEntry = entry;
}
}
reader.close();
return maxEntry;
}
4、IP排序
把通过后的最大IP,进行排序。代码如下:
public static void main(String[] args) throws Exception {
Test t = new Test();
String FileName = "d://100000000.txt";
t.genIP(FileName);
t.splitMiniFile(FileName);
List<Map.Entry<String, Integer>> entryList = new ArrayList<Map.Entry<String, Integer>>();
for (int i = 0; i < 1000; i++) {
entryList.add(t.statisIps(FileName + i));
}
Map.Entry<String, Integer> maxEntry = entryList.get(0);
for (int j = 1; j < 1000; j++) {
if (entryList.get(j).getValue() > maxEntry.getValue()) {
maxEntry = entryList.get(j);
}
}
System.out.println(maxEntry.getKey());
System.out.println(maxEntry.getValue());
}

浙公网安备 33010602011771号