大文本文件(接近7GB): 统计频数,Top K问题求解

本文介绍了一种解决大规模文件中寻找出现频率最高的IP地址的方法。通过将大文件拆分为多个小文件,并对每个小文件进行独立处理和统计,最后整合结果找出全局最频繁的IP。整个过程包括文件切分、小文件统计及结果汇总。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自

https://blog.youkuaiyun.com/qq_26437925/article/details/78531179

 

1 产生了一个1G行,每行一个[0,100000]区间的整数

2 top n 求解:

2.1 大文件分成小文件

把这个7G左右的大文件,按照读入数字的hashcode值分成1024个小文件(每个文件平均最大就7M左右)

这里写图片描述

这里写图片描述

2.2 小文件统计

对每个小文件,可以用堆,hash,内部排序等等方法进行处理; 
本例使用Java的HashMap

2.3 小文件的统计结果 再做一次统计 求出出现频数最高的那个数

结果:

这里写图片描述

java源代码

import java.io.*;
import java.util.*;

class IP implements Serializable {  

    private static final long serialVersionUID = -8903000680469719698L;  
    private String ip = "";  
    private int count;  

    public IP(String ip2, Integer integer) {  
        this.ip = ip2;  
        this.count = integer;  
    }  

    public int getCount() {  
        return count;  
    }  

    public String getIp() {  
        return ip;  
    }  

    public void setCount(int count) {  
        this.count = count;  
    }  

    public void setIp(String ip) {  
        this.ip = ip;  
    }  

} 

public class Data {

    static String fileLoc = "D:\\hadoop\\numsout\\nums.txt";  

    /** 
     * 将打文件hash成1024个小文件 
     *  
     * @throws FileNotFoundException 
     * @throws IOException 
     */  
    private static void hashToSmallFiles() throws FileNotFoundException, IOException {  
        BufferedReader br = new BufferedReader(new FileReader(fileLoc));  
        String ip = "";  
        HashMap<String, FileWriter> fileWriters = new HashMap<String, FileWriter>();  
        while ((ip = br.readLine()) != null) {  
            int tmp = Math.abs(ip.hashCode() % 1024);  
            String fileName = fileLoc + tmp + ".txt";  
            FileWriter fw = null;  
            if (fileWriters.containsKey(fileName)) {  
                fw = fileWriters.get(fileName);  
            } else {  
                fw = new FileWriter(fileName, true);  
                fileWriters.put(fileName, fw);  
            }  
            fw.write(ip + "\n");  
        }  
        br.close();  
        for (FileWriter ff : fileWriters.values()) {  
            ff.close();  
        }  
    }  

    /**
     * 利用HashMap<> 统计每个小文件频数最高的ip; 
     * @return 所有小文件的结果 组成List 返回
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static List<IP> countEverySmallFile() throws FileNotFoundException, IOException {  
        List<IP> list = new ArrayList<IP>();  
        for (int i = 0; i < 1024; i++) {  
            File file = new File(fileLoc + i + ".txt");  
            if (file.exists()) {  
                long startTime = System.currentTimeMillis();  
                BufferedReader br1 = new BufferedReader(new FileReader(file));  
                String ip1 = "";  
                HashMap<String, Integer> hm = new HashMap<String, Integer>();  
                while ((ip1 = br1.readLine()) != null) {  
                    if (!hm.containsKey(ip1)) {  
                        hm.put(ip1, 1);  
                    } else {  
                        hm.put(ip1, hm.get(ip1) + 1);  
                    }  
                }  

                IP[] ips = new IP[hm.size()];  
                int index = 0;  
                for (String temp : hm.keySet()) {  
                    ips[index] = new IP(temp, hm.get(temp));  
                    index++;  
                }  
                int max = 0;  
                for (int j = 1; j < ips.length; j++) {  
                    if (ips[j].getCount() > ips[max].getCount()) {  
                        max = j;  
                    }  
                }  
                list.add(ips[max]);  
                long endTime = System.currentTimeMillis();  
                System.out.println("已经统计文件:" + fileLoc + i + ".txt,用时:" + (endTime - startTime) + " 毫秒");  
            }  
        }  
        return list;  
    }  

    /** 
     * 从每个文件出现频率最高ip中,计算出所有文件中出现频率最高ip。 
     *  
     * @param list 
     */  
    private static IP calculateResult(List<IP> list) {  
        IP[] ips = new IP[list.size()];  
        ips = list.toArray(ips);  
        int max = 0;  
        for (int j = 1; j < ips.length; j++) {  
            if (ips[j].getCount() > ips[max].getCount()) {  
                max = j;  
            }  
        }  
        return ips[max];  
    }  

    public static void findIp() throws IOException, ClassNotFoundException {  

        long start = System.currentTimeMillis();  
        //hashToSmallFiles();  
        long end1 = System.currentTimeMillis();  
        System.out.println("将大文件映射成小文件,用时:" + (end1 - start) + "毫秒");
        System.out.println("将大文件映射成小文件,约:" + (end1 - start) / 60000 + "分钟");
        // 测试时大约28分钟

        System.out.println("映射到小文件完成,开始统计每个小文件中出现频率最高的ip");
        long start1 = System.currentTimeMillis();  
        List<IP> list = countEverySmallFile();  
        long end2 = System.currentTimeMillis();  
        System.out.println("统计所有文件共用时:" + (end2 - start1) + " 毫秒");
        System.out.println("统计所有文件共用时,约:" + (end2 - start1) / 60000 + "分钟");
    // 测试时大约13分钟        

        System.out.println("统计完成,开始计算所有ip中出现频率最高的ip");  
        IP ip = calculateResult(list);  
        System.out.println("访问次数最多的ip是:" + ip.getIp() + ":" + ip.getCount()); 
        long end = System.currentTimeMillis(); 
        System.out.println("公用时:" + (end - start) + "毫秒");  
    }

    // 产生大文件
    public static void getBigFile() {    
        try   
        {  
            File file = new File(fileLoc);           
            if(!file.exists())  
            {   //如果不存在则创建  
                file.createNewFile();  
                System.out.println("文件创建完成,开始写入");               
            }  
            FileWriter fw = new FileWriter(file);       //创建文件写入  
            BufferedWriter bw = new BufferedWriter(fw);  

            //产生随机数据,写入文件  
            Random random = new Random(); 

            for(int i=0;i<1024*1024*1024;i++)  
            {     
                int randint = (int)Math.floor((random.nextDouble()*100000.0));//产生【0,10000】之间随机数          
                bw.write(String.valueOf(randint));      //写入一个随机数  
                bw.newLine();       //新的一行  
            }  
            bw.close();  
            fw.close();  
            System.out.println("文件写入完成");
        }   
        catch (Exception e)   
        {  
            e.printStackTrace();  
        }         
    }

    public static void main(String[] args) throws Exception {

     //getBigFile();
     // 产生文件:有1024*1024*1024行(1G行),每一行一个数字      

         findIp();

     System.out.println("Finished");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值