笔试题:海量日志中提取访问次数前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。
画图应该好理解一点:
具体代码如下:
IP对象类:
测试代码:
有一篇博文说得好,扎实的基础跟开阔的视野才是企业所看重的。
关注时代的发展,学习能力强,愿意接受新事物才是企业所喜欢的,当然双向选择,一个创新,有挑战,能快,高,长大的企业也是雇员所喜欢的。加油~
Have a nice day~
今天就写写之前的一道笔试题:每个用户访问,系统都会记录用户的IP到日志中,一个小时产生1G的日志文件,请分析日志文件获取当天访问次数前100的IP(大概是这样)。
由于IP是32位的,最多有个2^32个IP,也就是4G,所以不能完全加载到内存中处理;可以采用映射的方法,按照IP地址的Hash(IP)%1024值,把整个大文件映射为1024个小文件,再依次分析每个小文中出现频率最大的前100个IP及相应的频率,因为涉及到排序,所以使用到了TreeSet。
画图应该好理解一点:
具体代码如下:
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~