统计外站的搜索关键词的词频

   统计外站的搜索关键词的词频
  
   通过外站的链接主要是百度,谷歌,soso等,每天都有通过记录在日志文件中,每天会运行程序进行统计。
每天产生有10多个文件,每个文件1G左右, 每个文件的每一行都存放的是用户的query,每个文件的query都可能重复。要按照解析query中的关键词,并对统计其频度,取出搜索次数最多的前1000个关键词。

第一次直接遍历所有文件并按照Map<String,Integer>方式来统计,统计差不多共有四千万条记录,词也有一百万多个,最后排序实现。方法简单,但也有很大的缺点,占用的内存太大,可能会将服务器弄垮掉。

 

/** * 初始写文件流 */ public void init() { if (numFiles < 1 && numFiles > 1000) { throw new RuntimeException("中间保存搜索关键词的文件数目不能小于1或大于1000"); } outs = new BufferedWriter[numFiles]; outFiles = new File[numFiles]; File tempDir = new File("temp"); if (!tempDir.exists()) { tempDir.mkdir(); } for (int i = 0; i < numFiles; i++) { try { outFiles[i] = new File("temp/" + String.valueOf(i)); outFiles[i].createNewFile(); outs[i] = new BufferedWriter(new FileWriter(outFiles[i])); } catch (IOException e) { throw new RuntimeException(e); } } }

     
先不统计,利用外存处理,将分析出来的每一个关键词,取出第一个字符的哈希值%500,分别放进500个临时文件中,然后才对每个文件进行统计。

 

 

/** * 记录关键词到相应的文件 * * @param keyword */ public void addKeyword(String keyword) { // 写入不同的外存(文件) if (keyword.length() < 1) return; String firstStr = keyword.substring(0, 1); int index = firstStr.hashCode() % numFiles; index = Math.abs(index); try { outs[index].write(keyword + lineSep); } catch (IOException e) { logger.error("", e); } }

 

 


由于只取前1000个关键词,所以每统计完一个文件后,采用堆排序,将前1000名的关键词保存在一个堆里,这样内存中只维护一份堆,可以减少许多内存的消耗,只占用到之前的五分之一以下。速度较之前也提高不少。

主要代码:
public List<Keyword> sortKeywordMap(int size) { final KeywordQueue queue = new KeywordQueue(size); try { TObjectIntHashMap<String> key2numMap = new TObjectIntHashMap<String>(); // 统计所有文件 for (int i = 0; i < numFiles; i++) { // 对单个文件统计 LineIterator lines = FileUtils.lineIterator(outFiles[i]); while (lines.hasNext()) { String line = lines.nextLine(); int num = key2numMap.get(line); num++; key2numMap.put(line, num); } lines.close(); // 将统计完的map中的所有关键词放入最小堆中 key2numMap.forEachEntry(new TObjectIntProcedure<String>() { @Override public boolean execute(String key, int num) { Keyword k = new Keyword(key, num); queue.insertWithOverflow(k); return true; } }); // 进行清除 key2numMap.clear(); } } catch (Exception e) { logger.error("", e); } List<Keyword> list = new ArrayList<Keyword>(); for (int i = queue.size() - 1; i >= 0; i--) { list.add(queue.pop()); } Collections.reverse(list); return list; }

你可能感兴趣的:(exception,String,list,File,Integer,query)