欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

笔试题:海量日志中提取访问次数前100的IP 博客分类: 数据结构与算法J2SE java面试大数据日志分析笔试 

程序员文章站 2024-03-25 14:08:52
...
大数据时代是一个信息量爆炸的时代,利用数据分析将会产生不可估量的价值,基金,证券,电商以及现在越来越火的O2O。当然作为一个热点,企业的笔试与面试中当然少不了关于大数据的问题。

今天就写写之前的一道笔试题:每个用户访问,系统都会记录用户的IP到日志中,一个小时产生1G的日志文件,请分析日志文件获取当天访问次数前100的IP(大概是这样)。

由于IP是32位的,最多有个2^32个IP,也就是4G,所以不能完全加载到内存中处理;可以采用映射的方法,按照IP地址的Hash(IP)%1024值,把整个大文件映射为1024个小文件,再依次分析每个小文中出现频率最大的前100个IP及相应的频率,因为涉及到排序,所以使用到了TreeSet。
画图应该好理解一点:
笔试题:海量日志中提取访问次数前100的IP
            
    
    博客分类: 数据结构与算法J2SE java面试大数据日志分析笔试 
具体代码如下:
package test.bigdata;
import java.io.*;
import java.security.SecureRandom;
import java.util.*;
public class LogAnalysis {
	//保存每个文件的流对象
	public final Map<Integer,BufferedWriter> bwMap = new HashMap<Integer,BufferedWriter>();
	//分隔文件用-存储相当数量之后再存入某个文件
	public final Map<Integer,List<String>> dataMap = new HashMap<Integer,List<String>>();
	//存储访问次数前100的IP
	public Set<IP> set = new TreeSet<IP>();
	
	// 生成日志文件
	public void creatLog(File log,long logNums) throws Exception{
		FileWriter fw = new FileWriter(log,true);
		BufferedWriter bw = new BufferedWriter(fw);
		SecureRandom random = new SecureRandom();
		for (int i = 0; i < logNums; i++) {
			bw.write("192."+random.nextInt(255)+"."+random.nextInt(255)+"."+random.nextInt(255)+"\n");
			if((i+1) % 1000 == 0){
				bw.flush();
			}
		}
		bw.flush();
		fw.close();
		bw.close();
	}
	
	// 分割日志文件
	public void splitLog(File logflie,int fileNums) throws Exception{
		FileReader fr = new FileReader(logflie);
		BufferedReader br =new BufferedReader(fr);
		String ip = br.readLine();
		//先创建文件及流对象方便使用
		for(int i=0;i<fileNums;i++){
			File file = new File("D:\\javasoft\\TempTest\\BigData\\logSplit\\"+ i + ".txt");
			bwMap.put(i, new BufferedWriter(new FileWriter(file,true)));
			dataMap.put(i, new LinkedList<String>());
		}
		while(ip != null){
			int hashCode = ip.hashCode();
			hashCode = hashCode < 0 ? -hashCode : hashCode;
			int fileNum = hashCode % fileNums;
			List<String> list = dataMap.get(fileNum);
			list.add(ip + "\n");
			if(list.size() % 1000 == 0){
				BufferedWriter writer = bwMap.get(fileNum);
				for(String line : list){
					writer.write(line);
				}
				writer.flush();
				list.clear();
			}
			ip = br.readLine();
		}
		for(int fn : bwMap.keySet()){
			List<String> list = dataMap.get(fn);
			BufferedWriter writer = bwMap.get(fn);
			for(String line : list){
				writer.write(line);
			}
			list.clear();
			writer.flush();
			writer.close();
		}
		bwMap.clear();
		fr.close();
		br.close();
	}
	
	//分析统计,找出次数前100的IP
	public void analysis(File logSplit) throws Exception{
		FileReader fr = new FileReader(logSplit);
		BufferedReader br =new BufferedReader(fr);
		String ip = br.readLine();
		//临时temp1存储当前文件所有IP
		Set<IP> temp1 = new TreeSet<IP>();
		while(ip != null){
			ip = ip.trim();
			temp1.add(new IP(ip,1));
			ip = br.readLine();
		}
		br.close();
		fr.close();
		//提取temp1存储当前文件访问次数前100的IP并将其与set合并
		int i=0;
		for (IP o : temp1) {
			set.add(o);
			if (i>100) {
				break;
			}
			i++;
		}
		//临时temp2截取已经合并的set中前100的IP
		Set<IP> temp2 = new TreeSet<IP>();
		for (IP o : set) {
			temp2.add(o);
			if (i>100) {
				break;
			}
			i++;
		}
		//使得set一直存储目前已经分析访问次数前100的IP
		set = temp2;
		temp2=null;
		temp1=null;
	}
}

IP对象类:
class IP implements Comparable<IP>{
	public String ip;
	public int nums;
	public IP(){}
	public IP(String ip,int nums){
		this.ip = ip;
		this.nums = nums;
	}
	@Override
	public int compareTo(IP o) {
		if (this.ip.equals(o.ip)) {
			o.nums=this.nums+o.nums;
		}else {
			if (this.nums > o.nums) {
				return -1;
			}else{
				return 1;
			}
		}
		return 0;
	}
}

测试代码:
package test.bigdata;
import java.io.*;
public class TestIP {
	public static void main(String[] args) throws Exception{
		//生成模拟日志文件
		LogAnalysis logAnalysis = new LogAnalysis();
		File log = new File("D:\\javasoft\\TempTest\\BigData\\ip.txt");
		log.createNewFile();
		logAnalysis.creatLog(log, 10000);//节省时间
		
		//分割日志文件
		logAnalysis.splitLog(log, 1024);
		
		//分析文件
		File logSplits = new File("D:\\javasoft\\TempTest\\BigData\\logSplit");
		for (File logSplit : logSplits.listFiles()) {
			logAnalysis.analysis(logSplit);
		}
		for (IP o : logAnalysis.set) {
			System.out.println(o.ip+"---"+o.nums);
		}
	}
}

有一篇博文说得好,扎实的基础跟开阔的视野才是企业所看重的。
关注时代的发展,学习能力强,愿意接受新事物才是企业所喜欢的,当然双向选择,一个创新,有挑战,能快,高,长大的企业也是雇员所喜欢的。加油~

Have a nice day~笔试题:海量日志中提取访问次数前100的IP
            
    
    博客分类: 数据结构与算法J2SE java面试大数据日志分析笔试 


  • 笔试题:海量日志中提取访问次数前100的IP
            
    
    博客分类: 数据结构与算法J2SE java面试大数据日志分析笔试 
  • 大小: 46.2 KB