小玩具——单词词频统计

小玩具——单词词频统计

该程序是在我学习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;
		}      	
   }



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值