天天看点

福大软工1816 · 第二次作业-个人项目

Part 1.卷首语

github传送门

本次的开发环境
  • Windows 10 64bit + Eclipse + JProfiler

Part 2.PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 ---
· Estimate · 估计这个任务需要多少时间 10 20
Development 开发
· Analysis · 需求分析 (包括学习新技术) 120 150
· Design Spec · 生成设计文档 30
· Design Review · 设计复审
· Coding Standard · 代码规范 (为目前的开发制定合适的规范)
· Design · 具体设计 60 40
· Coding · 具体编码 700 1320
· Code Review · 代码复审
· Test · 测试(自我测试,修改代码,提交修改)
Reporting 报告
· Test Repor · 测试报告
· Size Measurement · 计算工作量
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划
合计 1080 1830

Part 3.解题思路

首先问题的大致要求是需要统计文本中的各参数数量与词频,整体的先后思路如下:

  • 1.首先要做的事情就是将.txt中的文本转换为可操作的字符串(结果还需要写入.txt文件中),这个过程关系到文件流操作;
  • 2.对于可操作的字符串,要对其进行筛选、转化、切割、选择(开头4个字母后含若干个字母数字的形式);
  • 3.对于处理后的单词集,需要对其进行词频统计,并在统计结束后排序好先后顺序传回主函数,基本任务完成。

Part 4.实现过程

  • countChar:负责字符数的统计;
  • countVec:负责单词数的统计;
  • countLine:负责行数的统计;
  • createMap:负责处理HashMap词频表的建立
    福大软工1816 · 第二次作业-个人项目

Part5.关键代码展示

简单的列出主要花费自己心思去写的两部分代码,其余的详细请见github上的源码。

对于单词的选择,我主要利用的是正则匹配的方式来选择,先将内部不符合的元素用某一符号代替,而这一符号将作为下一次分隔符标志,利用Pattern和Matcher去除非英文数字字符,而后进一步对单词的样式进行约束,对于符合正则表达式的单词加入列表中提供给后续使用

public static int countwords(int count,String text){
		list.clear();	//做初始化清空字符集处理
		String regex ="[^0-9a-zA-Z]";	//剔除文本中的非字母和数字的部分并以!作为暂时的分隔符
		Pattern pat = Pattern.compile(regex);
		Matcher mat = pat.matcher(text);
		text = mat.replaceAll("!");				
		String [] textArray = text.split("!+");		//按照分隔符划分
		String v_regex = "^[a-z]{4}[a-z0-9]*$";		//对单词形式进行约定
		for(String i:textArray){
			Pattern v_pat = Pattern.compile(v_regex);
			Matcher v_mat = v_pat.matcher(i);
			if(v_mat.matches())
				list.add(i);
		}
		return list.size();
	}
           

对于词频分类和统计,这里利用了HashMap,简单且易查找,<Key,Value>的形式很好的记录了<单词本身,出现次数>这样的记录。最后将记录好的Map进行排序,按照题给要求,先以Value值做参考,在Value值相同的情况下,以Key值优先为准。

public static List<Map.Entry<String,Integer>> createHashMap(List<String>list){
		Map<String,Integer> ver = new HashMap<String, Integer>();
		for(String i:list){
			if(!ver.containsKey(i))
				ver.put(i, 1);
			else{
				Integer num = ver.get(i);
				ver.put(i, num+1);
			}
		}
		List<Map.Entry<String,Integer>> verlist = new ArrayList<Map.Entry<String,Integer>>(ver.entrySet());
		Collections.sort(verlist,new Comparator<Map.Entry<String, Integer>>(){
			public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2) {
				if(o1.getValue()==o2.getValue()){
					return (o1.getKey()).compareTo(o2.getKey());
				}
				return o2.getValue()-o1.getValue();
	        }
		});
		return verlist;
	}
           

下面主要是我对于IO操作的异常进行处理的基本形式

public static int countChar(String path,int count) throws IOException{
		try {
			...
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}finally{
			...
		}
		return count;
	}
           

Part6.性能分析

福大软工1816 · 第二次作业-个人项目
福大软工1816 · 第二次作业-个人项目

以下主要是调用各个不同类中的接口,所以Main中的覆盖率会为0,整体的情况符合正常的操作结果。

福大软工1816 · 第二次作业-个人项目
福大软工1816 · 第二次作业-个人项目

进行单元测试的过程中,可通过如下的报错来寻找自己的疏漏之处,每一环节都能够很好的定位到。

福大软工1816 · 第二次作业-个人项目

Part7.感想

有了初步的构思以后,边学习边敲java代码,实践中去逐步的完善自己,总体来说,我对自己的表现还是挺满意的。过程中接触了单元测试,找到了自己许多原先疏漏的小细节,在逐步改进之下完善着自己的代码。怎么说呢,可能还是自己的慢性子的原因,每天都在投入时间去边敲边改,但是很遗憾,得出最终成果的时间还是压到了接近与deadline之前一些些,所以我对自己下一次任务的期望是自己能够有更高的效率,达到更好的效果,以上。

福大软工1816 · 第二次作业-个人项目

也希望大家能够对我提出宝贵的意见,谢谢大家,小废的程序员之路道阻且长......

Part8.后记

后续在完成作业以后,看到了许多同学都有意识的去讨论测试数据的大小问题,所以自己也做了一下大型文本的测试,果然发现出错。总结一下自己得出的结论:String对于连接操作(“+”)效率很低,因此导致了我程序一直没办法正常运行,后改用StringBuilder,利用.append()方法来进行文本的逐行拼接,成功解决了上述所困扰我的问题。(更新代码内容详见github源码部分),后续将会对为什么String效率低的问题分析好后作出解释,暂告一段落,谢谢(附上大型数据测试情况)

这里简单的结合office word自带的字数统计功能校验如下:

福大软工1816 · 第二次作业-个人项目