把访问P站次数最多的那个人才给我找出来?

如果我掌握了P站的所有访问日志数据(海量),我想找出某一天访问次数最多的那个IP,并看看到底是那个国家的小哥精力如此旺盛???

对于这种问题,说到底,就是一个“分与合”的思想。

 

我们需要从访问P站日志中,把具体某一天的所有IP取出来,再逐个写入到一个大文件中。值得一提的是,IP是32位的,那么就有2^32个IP,就算扣除特殊IP,在重复量小的情况下,一般来说,不能直接把这些数据放入到内存里面。

 

这里的话,我们需要采用hash映射的方法,比如取模1000,把这个大文件分割成1000个小文件,再去小文件中找出出现频率最大的IP,并记录其出现频次;最后,再从这1000个IP中找到出现频次最大的IP,这样便把一个看似不能解决的问题就给解决了。

具体操作:

  1. 对IP地址进行hash(IP)%1000求值,再把海量IP日志分别存储到1024个小文件中;

  2. 分别对每一个小文件,构建一个{k:IP ,v:频次}的map,并记录下当前小文件频次最多的IP;

  3. 对得到的这个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());
    }

 

  

  

posted @ 2020-03-20 17:15  Mr_Echo  阅读(499)  评论(0编辑  收藏  举报