- 作业地址:
https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1816W/homework/2085
一、Github地址
https://github.com/xshl/PersonProject-Java2
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 20 |
• Estimate | • 估计这个任务需要多少时间 | 10 | 20 |
Development | 开发 | 335 | 515 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 120 |
• Design Spec | • 生成设计文档 | 10 | 10 |
• Design Review | • 设计复审 | 20 | 15 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 15 | 25 |
• Design | • 具体设计 | 30 | 35 |
• Coding | • 具体编码 | 200 | 420 |
• Code Review | • 代码复审 | 20 | 30 |
• Test | • 测试(自我测试,修改代码,提交修改) | 130 | 360 |
Reporting | 报告 | 55 | 60 |
• Test Repor | • 测试报告 | 20 | 20 |
• Size Measurement | • 计算工作量 | 20 | 15 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 15 | 25 |
合计 | 550 | 1095 |
三、解题思路&学习历程
- 解题思路
刚拿到题目的时候没什么头绪,第一反应就是去遍历。事实上我也是这么做的
-
- 统计文件的字符数(charCount.java)
- 根据编码判断每个字符是不是我们所需要的。
- 由于换行符占两个字符但是在我们计算的时候换行符只算一个字符,所以最终的字符数要减去行数才是最终的数量。
- 统计文件的单词总数
- 根据分隔符进行单词分割,并判断是否符合单词要求。
- 但是存在一个问题,分割符是列举的,会存在遗漏现象。
- 采用正则表达式
- 统计文件的行数
- 通过readLine()获取行数
- 并识别换行符
- 统计单词频率,并输出频率最高的10个
- 在分割出单词之后,将单词遍历储存在hashmap当中,在储存前先判断是否为合法单词
- 将map的遍历储存在set当中
- 统计文件的字符数(charCount.java)
- 学习历程
在决定用java书写之后,就把之前借的疯狂Java讲义翻了出来,看了下如何读和写txt。对于map的排序问题,看了csdn上的一些博客,然后通过自己的理解,写出了统计频率的函数。
-
- 学习JAVA hashmap的使用以及排序
- 学习正则表达式(但还没用)
四、计算模块接口的设计与实现过程
Main.java函数调用其它函数实现相应的功能
- 统计文件的字符数(charCount.java)
1 while((value = bReader.read()) != -1) { 2 if (value >= 0 && value<=255) { 3 charcount++; 4 } 5 }
- 统计文件的单词总数(wordCount.java)
1 while ((line = bufferedReader.readLine()) != null) { 2 String[] words = line.split("[^a-zA-Z0-9]+"); 3 for (String word : words) { 4 word.toLowerCase(); 5 if (word.matches("[a-zA-Z]{4}[a-zA-Z0-9]*") ) { 6 countword++; 7 } 8 } 9 }
- 统计文件的行数
1 while ((line = bufferedReader.readLine()) != null) { 2 if (line.length() != 0 && !line.matches("\\s+")) { 3 linecount++; 4 } 5 }
- 统计单词频率,并输出频率最高的10个
- 在分割出单词之后,将单词遍历储存在hashmap当中,在储存前先判断是否为合法单词
String str=st.nextToken(); str = str.toLowerCase(); if ((str.charAt(0) >= '9' || str.charAt(0) <= '0') && str.length() >= 4) { if(map.containsKey(str)) map.put(str, map.get(str)+1); else map.put(str, 1);
}
-
- 将map的遍历储存在set当中
Set<WordEntity> set=new TreeSet<WordEntity>(); for(String s:map.keySet()){ WordEntity wordEntry=new WordEntity(s,map.get(s)); set.add(wordEntry); } Iterator<WordEntity> ite=set.iterator(); int count=0; while(ite.hasNext()){ if(count>=10) break; System.out.println(ite.next()); count++; }
五、计算模块接口部分的性能改进
从最初的暴力解决一步步改善用hashmap存储对单词的遍历,map的遍历存储在set中,排序 TreeSet,对wordEntity实现comparable接口重写compareTo()和toString()。
1 @Override 2 public String toString() { 3 writeInTxt.writeTxt( "<" + word + ">:" + count); 4 return "<" + word + ">:" + count; 5 } 6 @Override 7 public int compareTo(WordEntity O) { 8 int cmp=count.intValue()-O.count.intValue(); 9 return (cmp==0?word.compareTo(O.getKey()):-cmp); 10 }
接口:
1 public interface WordCount { 2 3 /** 4 * 返回行数 5 * @param filename 6 * @return 7 * @throws IOException 8 */ 9 int linesCount(String filepath) throws IOException; 10 11 /** 12 * 返回合法单词数 13 * @param filepath 14 * @return 15 * @throws IOException 16 */ 17 int wordsCount(String filepath) throws IOException; 18 19 /** 20 * 返回字符数 21 * @param filepath 22 * @return 23 * @throws IOException 24 */ 25 int charsCount(String filepath) throws IOException; 26 27 /** 28 * 词频前十的单词 29 * @param filepath 30 * @throws IOException 31 */ 32 void wordDetail(String filepath) throws IOException; 33 }
六、计算模块部分单元测试展示
- 通过单元测试,暂时未发现bug
- 测试数据
-
- 测试结果
- 补充(9月13日):在进行单元测试时未发现bug。
- 代码覆盖率,其中未覆盖到的大部分为异常处理
- 其中wordDetail.java耗时最长,因为在这个函数中涉及了排序
七、计算模块部分异常处理说明
try{ 可能发生异常的代码块 }catch(异常1){ 处理异常1的代码 }
七、感悟
之前接触JAVA都是在Android开发和上学期的数据库作业中,原本觉得做起来会轻松一点,但是在这次的实践中做的很吃力,而且效果也很不理想,对一些JAVA的知识了解的还不够深,想HashMap、TreeSet等,花了很多时间在查资料和学习上,比自己预计的时间多了很多,接下来还是要好好学习基础。在以前使用JAVA写项目的时候,都没有尝试过做单元测试,平常找错都是讲结果输出看,这次做单元测试也是查了网上的资料,再慢慢尝试。代码还存在一个问题,运行之后在将结果写入result.txt之后不会清除之前的记录,只会添加。
更新(9.13)
运行结果写入result.txt之后不会清除之前的记录问题已解决。在Main函数中添加以下代码。由于之前是在writeInTxt中写这段代码,导致每次调用writeInTxt时都清除了一遍,只显示最后一个写入的。
File file1 = new File(".\\result.txt"); if (file1.exists() && file1.isFile()) { file1.delete(); }
补充:在提交的时候只测试了自己的样例,单词句子数量比较少,没有出错。提交的是使用比较暴力的分割方法做的,接下来打算采用正则表达式进行改善,已用正则改善。