词频统计

  • 作业地址:

https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1816W/homework/2085

一、Github地址

https://github.com/xshl/PersonProject-Java2

 二、PSP表格

PSP2.1Personal 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当中
  • 学习历程

在决定用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();
}

补充:在提交的时候只测试了自己的样例,单词句子数量比较少,没有出错。提交的是使用比较暴力的分割方法做的,接下来打算采用正则表达式进行改善,已用正则改善。

原文地址:https://www.cnblogs.com/xsl-/p/9634204.html