zoukankan      html  css  js  c++  java
  • 小玩具——单词词频统计

    小玩具——单词词频统计

    该程序是在我学习JAVA过程中的一个偶然想法,距离现在很久了,现在回顾一下这个程序的编写过程,有一天我正在背CET-4单词,实在是很煎熬啊,看着好厚一本俞敏洪的CET-4,我实在是感到很不开心,背着背着,我在想如果能够找出所有从2000年到本年的卷子中的单词频率,是否会使背单词容易些?我简单在大脑中“验证”了一下设计方法,验证通过,也许是不想背单词,我立刻被这个很好的不背单词“借口”所打动,立刻奔向实验室,开始编码。

    最终的编码结果:

     

     处理的源文件截图:

     

    最终的处理结果(20039月四级试题):

     

     

    正如大家所看到,输入文件为:从网上下载的不加修改的试题,输出为处理好的,对于每一种出现的英文单词的词频,[单词 该单词词频]

     

    现在我们来回顾一下制作过程,我也是时隔很久之后来回忆,尽力全面,也对该程序做一个反思:

    最初的设计,是使用数据库来存储词频的,为什么用数据库呢,因为当时正在学习数据库,我就现学现用,因此我使用了MYSQL数据库来存储每一个单词的词频变化,最终寄希望于在数据库中生成一个每个单词的词频统计数据。

    当时我建立了一个表,该表极为简单,只有两列:单词,词频。这样做显然也是很简单的,我只需要做 查找、修改和更新的操作。而大部分的程序就不需要我自己写了,好懒啊~

    首先,我来呈现一下当时的想法:

    1、对文本中非英语的一切字符进行过滤,只留下英语和必要的空格(标点符号换成空格,空格能够区分不同单词,同时对于英语中特别的字符要加以处理)

    2、过滤出单词

    3、对单词首先在数据表中“查找”操作,如果存在,则更新值,如果不存在,则插入值。

    4、寻找合适的呈现方法,将最终的数据呈现出来,表格、文件等

    此想法是非常不错的,但是在实施过程中,遇到了一个棘手的问题,在对单个年份的文档进行处理的时候是可以的,但是对于数十年的文档处理时候,会报一个数据库连接池到达最大连接数的错误。

    在该错误出现后,对该错误进行反复测试,发现为可重现错误,首先对自己的程序进行检查,尽量再次优化减少存储数据库的次数(当然想到了再次建立内存中的检索模型,但是一旦这样做,我可不能偷懒了,这又不是商业项目,我只是想要结果而已),我修改了数据库连接池的参数,仍然出现问题,而且出现问题的连接次数我做过统计,似乎浮动于某个固定值(此值目前已忘记),因此可以认为是一个固定限制,而且影响该次数的应该不止有我的程序,否则不会出现浮动的现象。

    考虑到win系统看待连接数据库的方式,我认为应该与系统有关,因此查阅网络上有关连接数据库的相关资料,特别是系统方面的相关资料,发现是winxp系统对于连接数据库有上限的,根据我所使用的XP系统的版本,我按照微软官方的方法进行调整,但是调整后没有效果,调整后重新启动,仍然没有效果……,查看网络上有些人遇到了跟我一样的问题,调整后仍然无法解决,所以看来这个懒是没法偷了。

    考虑更改软件的设计,不采用数据库来存储了,经历这个事件,对数据库的练习还是实现了其价值的,现在就关心怎么出结果。

    不使用数据库,首先我想到了构建一组内存结构,其实也很简单,主要构造一个类,用来存储word和词频,只需要两个变量,由于我只是用于一次,可以不考虑数据封装,只是用public来限制变量,但是我想,更好的方法是不建立类,直接使用Map,在JAVA中这些容器非常好用,而且速度也非常快,我选择HashMapMAP本身就是“键-值”类型,键用来存储word,值用来存储词频,哈哈偷懒成功。

    所以后来程序的设计为:

    1、对文本中非英语的一切字符进行过滤,只留下英语和必要的空格(标点符号换成空格,空格能够区分不同单词,同时对于英语中特别的字符要加以处理)

    2、过滤出单词

    3、对单词首先在MAP中“查找”操作,如果存在,则更新值,如果不存在,则插入值。

    4、寻找合适的呈现方法,将最终的数据呈现出来,表格、文件等

     

    其实就是一个小玩具而已,现在给出核心代码(很早前写的代码,不足之处请包涵):

     

    变量设定:

    Map map=new HashMap();
       File inputStr=new File(from);  //打开输入文件
       File outputStr=new File(dest); //建立输出文件
    FileInputStream fi=new FileInputStream(inputStr); //输入流
    	FileWriter fwout=new FileWriter(outputStr);  //输出流
    			
    我很偷懒的占用内存来作恶了,哈哈。现在来看这里不能这样做,我们可以读入一段处理一段,
    建立两个对称大小的缓冲区,灵活使用,防止由于缓冲区大小不够造成单词被截断的情况发生:
     byte[] c=new byte[5500000];  //字符集合
     
    
    过滤出单词:
    for(int i=0;i<c.length;i++){
    if((65<=c[i]&&c[i]<=90)||(97<=c[i]&&c[i]<=122)||c[i]==32||c[i]==39||c[i]==46||c[i]==44)
    	if(c[i]==32) {
    		String tmp=str.substring(p, i);
    		String retmp=tmp.trim();
    		if(!retmp.equals("")){ 				   	         						
    			frontstr+=retmp;
    	if (map.get(retmp)==null){ 
           map.put(retmp, 1);
    		}else{
    			int old=Integer.parseInt(map.get(retmp).toString());
    			map.put(retmp, old+1);
    		}
    		p=i;}
    	}
    	}
    输出(包含排序,词频最大在前):
    Set set=map.keySet();
    while(!map.isEmpty()){
    int max=0,point=0;
    Object[] keySet=set.toArray();
    for(int i=0;i<keySet.length;i++){
    	if (Integer.parseInt(map.get(keySet[i]).toString())>=max) 
    		{max=Integer.parseInt(map.get(keySet[i]).toString());
    		point=i;
    		}      	
       }
    
    欢迎转载,转载请注明出处。本文出自:http://www.cnblogs.com/zdcaolei
    0
  • 相关阅读:
    生成更大的陆地 Making A Large Island
    HDU 3342 Legal or Not【拓扑排序】
    POJ 2367 Genealogical tree【拓扑排序】
    CodeForces Round #290 Div.2
    HDU 1010 Tempter of the Bone【DFS】
    HDU 1312 Red and Black【DFS】
    POJ 1664 放苹果【DFS】
    HDU 1587 Flowers【贪心】
    Codeforces Round #289 Div 2
    HDU 1241 Oil Deposits【DFS】
  • 原文地址:https://www.cnblogs.com/zdcaolei/p/2408263.html
Copyright © 2011-2022 走看看