关于海量数据TopK问题的一个具体实现(java)
来源:互联网 发布:pvp网游 知乎 编辑:程序博客网 时间:2024/06/08 07:24
例题:搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。
本题的解法思路有几种,本文只提供其中一种实现,即HashMap+堆
第一步:
Hash统计,创建一个key为查询字串,value为次数的Hash表,插入记录时,如果已经存在该记录,则把该记录的value+1,否则插入一个value为1的记录。整个过程的时间复杂度为log(n);
第二步:
维护一个大小为K的小顶堆,最先存储的是先从Hash表中遍历到的K的记录,继续遍历,每次把得到的元素与对顶元素比较,如果大于则调整堆,小于则跳过继续。整个过程时间包括,建堆和多次更新堆的时间,整体的时间复杂度为nlog(k);
示例代码:
/** * @author hduser * */import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;/* * * 关键字:TopK,url统计,最小堆 * */public class TopK {//每行封装成一个记录,便于以后处理其他信息,如时间等等static class Record{private String searchKey;public String getSearchKey() {return searchKey;}public void setSearchKey(String s) {this.searchKey = s;}public Record() {}}public static void main(String[] args) {Map<String,Integer> map=new HashMap<String,Integer>();File f=new File("/home/hduser/TopKTest.txt");BufferedReader reader=null;int k=3;//测试用例记录较少,这里指定为3Record record=new Record();try {reader=new BufferedReader(new FileReader(f));String tmp="";while((tmp=reader.readLine())!=null){record.setSearchKey(tmp);insert(record,map);}Iterator iter=map.entrySet().iterator();while(iter.hasNext()){Map.Entry e=(Map.Entry) iter.next();System.out.println(e.getKey()+" "+e.getValue());}Map.Entry[] result=getTopKRecord(map,k);for(Map.Entry<String,Integer> e:result){System.out.println(e.getKey()+" "+e.getValue());}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//Hash表统计次数private static void insert(Record record, Map<String, Integer> map) {String url=record.getSearchKey();if(map.containsKey(url)){map.put(url, map.get(url)+1);}elsemap.put(url, 1);}//维持一个大小为k的最小堆public static Map.Entry[] getTopKRecord(Map<String, Integer> map,int k){int i=0;Iterator iter=map.entrySet().iterator();Map.Entry[] elements=new Map.Entry[k];while(iter.hasNext()){Map.Entry e=(Map.Entry) iter.next();if(i<=k-1){elements[i]=e;if(i==k-1){buildMinHeap(elements);}i++;}else{insertHeap(e,elements);}}return elements;}private static void insertHeap(Map.Entry n, Map.Entry[] heap) {if((int)n.getValue()>(int)heap[0].getValue()){heap[0]=n;minHeap(heap,0,heap.length);}} private static void buildMinHeap(Map.Entry[] heap) {int i=heap.length/2-1;for(;i>=0;i--){minHeap(heap,i,heap.length);}}private static void minHeap(Map.Entry[] heap, int i, int length) {int left ,right,min;Map.Entry temp;left=2*i+1;right=2*i+2;min=i;if(left<=length-1&&(int)heap[left].getValue()<(int)heap[i].getValue()){min=left;}if(right<=length-1&&(int)heap[right].getValue()<(int)heap[min].getValue()){min=right;}if(min!=i){temp=heap[i];heap[i]=heap[min];heap[min]=temp;minHeap(heap,min,length);}}}
TopKTest.txt中的内容为:
helloworldhelloworldhelloareyounihaoyouyounihaoarehihiamhashas
结果为:
are 2hello 3you 3功力不够,欢迎指教。
0 0
- 关于海量数据TopK问题的一个具体实现(java)
- 海量数据的topK问题
- 海量数据的TopK问题
- 求海量数据的topK问题
- # 海量数据下的TopK问题
- 海量数据中找出前k大数(topk问题)
- 海量数据中找出前k大数(topk问题)
- 海量数据中找出前k大数(topk问题)
- 海量数据Topk及重复问题
- topk问题java实现
- 海量数据topK算法
- 海量数据取topk
- 海量处理topk问题
- Spark下的TopK实现(Java)
- TopK问题,在海量数据中寻找最大的K项
- 海量数据中,找出出现次数TOPK的记录
- 面试经典的海量数据处理(TOPK)问题—转载+个人见解!
- Java解决TopK问题(使用集合和直接实现)
- 关于java的视频资料分享
- 取代DataTable.Select方法,并动态拼接Lambda表达式
- EEPlat引擎运行流程
- 电路板阻抗原理知识及应用
- 门禁管理系统 项目计划书
- 关于海量数据TopK问题的一个具体实现(java)
- 【模式识别】K-近邻分类算法KNN
- linux上Weblogic 新建域,部署工程项目
- List.add()方法中的陷阱
- vs2010 显示汇编代码
- 【Android】动态UI : LayoutParams.addRule(...) LayoutParams.addRule(..., ...)
- SQL Server数据库备份还原时,提示“数据库正在使用”的解决办法
- 在Struts 2中实现IoC
- 【3D】迭代最近点算法 Iterative Closest Points