1. github链接

第一次个人编程作业

2. PSP表格

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

3. 模块接口的设计与实现

3.1 使用simHash来计算文本相似度

simhash算法分为5个步骤:分词、hash、加权、合并、降维,流程图如下所示:

第一次个人编程作业_流程图

3.2 类和函数的设计

类和函数的主要关系如下所示:

第一次个人编程作业_文本相似度_02

  • FileUtil类:读取文件和写文件的类
  • SimHash类:实现simHash算法
  • StringUtil类:对文本内容进行过滤
  • MainProcess类:主函数类,函数的入口

函数运行的关系

从MainProcess类的函数入口开始,读取指定的两个文件的内容,调用StringUtil类对文本内容进行过滤。对过滤完的文本进行SimHash运算,计算两者的海明距离,最后得出文本相似度,通过FileUtil的写文件函数将文本相似度写入指定的文件。

3.3 关键函数的实现

3.3.1 计算字符串的simHash

计算simHash的过程分为五个过程:

  1. 分词

    使用StandardTokenizer类对文本内容进行分词

  2. 计算hash

    调用hash(String)方法对分词计算hash

  3. 加权

  4. 合并

  5. 降维

下面为该函数的流程图:

第一次个人编程作业_html_03

3.3.2 对文件中的文本内容进行处理

由于文件中可能是纯文本内容,也可能是html文件。因此,这里需要对读取的文件内容进行处理。

首先,利用正则表达式判断文本中是否有html标签,是否是html文件:

  • 如果是html文件,那么使用jsoup包对html进行解析。
    • 观察过老师给出的测试文件后,发现真正的文本内容是在tr标签的td标签下。于是,使用jsoup包的方法提取tr标签下的td标签的内容。
    • 提取完文本内容后,由于文本相似度与标点符号和空格无关,因此这里需要将标点符号和空格删除,否则相同的文字会因为不同的标点符号或空格而导致不一样的相似度。
  • 如果不是html文件,直接对文本内容进行处理--删除标点符号和空格。

下面为该函数的流程图:

第一次个人编程作业_文件名_04

4. 计算模块的性能改进

使用JUnit4进行单元测试,使用Profile进行性能分析。

4.1 总体性能

第一次个人编程作业_文件名_05

4.2 CPU

第一次个人编程作业_流程图_06

4.3 类内存占用

第一次个人编程作业_流程图_07

4.4 函数耗时

第一次个人编程作业_文件名_08

从函数耗时中可以看出耗时最长的是计算simHash的方法。由于这里运用了hanlp的分词以及要计算hash,因此耗时最长。目前不具备性能改进的方法。

5. 单元测试

5.1 部分单元测试代码展示

第一次个人编程作业_文本相似度_09

5.2 构造测试函数的思路

这里一共构造了10个测试函数。主要从以下方面来构造:

  • 接收的文件不存在
  • 接收的参数为null
  • 对测试数据分别测试
  • 判断过滤后的纯文本和html文本是否相等
  • 对纯文本和html文本进行查重

5.3 单元测试覆盖率

第一次个人编程作业_html_10

6. 异常处理

6.1 文件名称为null

第一次个人编程作业_流程图_11

第一次个人编程作业_html_12

第一次个人编程作业_文本相似度_13

当文件名为null时,throw一个FileNotFoundException的异常,在处理文件内容的方法中直接将异常往上抛,最终在MainProcess的函数入口中try异常,并停止运行下去。

测试样例

第一次个人编程作业_html_14

对应场景

使用者在运行jar包时故意将文件名写为null,以防接下来的方法中报出空指针异常。

6.2 文件不存在

第一次个人编程作业_文本相似度_15

第一次个人编程作业_html_12

第一次个人编程作业_文本相似度_13

当文件不存在或者不是文件时,throw一个FileNotFoundException的异常,在处理文件内容的方法中直接将异常往上抛,最终在MainProcess的函数入口中try异常,并停止运行下去。

测试样例

第一次个人编程作业_html_18

对应场景

运行jar包时传入的文件地址不存在或者对应的不是文件,以防读取不到内容。