第一次个人编程作业
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/Networkengineering1834 |
|---|---|
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/Networkengineering1834/homework/11146 |
| 这个作业的目标 | <实现论文查重算法,熟练使用PSP表格,熟练使用单元测试,熟练使用代码质量检测工具,熟练使用性能分析工具,熟悉用git提交代码到GitHub> |
一、Github仓库
二、PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 20 |
| · Estimate | 估计这个任务需要多少时间 | 20 | 30 |
| Development | 开发 | 300 | 580 |
| · Analysis | 需求分析 (包括学习新技术) | 120 | 180 |
| · Design Spec | 生成设计文档 | 30 | 40 |
| · Design Review | 设计复审 | 20 | 20 |
| · Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
| · Design | 具体设计 | 60 | 60 |
| · Coding | 具体编码 | 120 | 200 |
| · Code Review | 代码复审 | 60 | 60 |
| · Test | 测试(自我测试,修改代码,提交修改) | 60 | 120 |
| Reporting | 报告 | 180 | 300 |
| ·Test Report | 测试报告 | 90 | 200 |
| ·Size Measurement | 计算工作量 | 10 | 10 |
| ·Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 10 | 30 |
| Total | 合计 | 1140 | 1960 |
三、计算模块接口的设计与实现过程。
1、算法原理:
初始句子:
句子A:这只皮鞋号码大了。那只号码合适。
句子B:这只皮鞋号码不小,那只更合适。
第一步,分词:
句子A:这只/皮鞋/号码/大了。那只/号码/合适。
句子B:这只/皮鞋/号码/不/小,那只/更/合适。
第二步,获取对比字典:
这只, 皮鞋, 号码, 大了, 那只, 合适, 不, 小, 更
第三步,计算词频:
句子A:这只1,皮靴1,号码2,大了1。那只1,合适1,不0,小0,更0
句子B:这只1,皮靴1,号码1,大了0。那只1,合适1,不1,小1,更1
第四步,写出词频向量:
句子A:(1,1,2,1,1,1,0,0,0)
句子B:(1,1,1,0,1,1,1,1,1)
第五步,计算两个句子向量:
使用公式:

计算过程:

计算后得到的结果越大,两篇文章的相似度就越大。
2、算法流程:

3、设计与实现:
Text类:用于对文件读出与写入:
fileToString(String filePath)方法:用于读出filePath文件中的内容,并转换成字符串返回。
saveStringToFile(String text, String filePath)方法:用于创建filePath文件,并把text写入文件。
Tokenizer类:用于分词
getTokenizer(String context)方法:用于对context分词,存入List集合返回。
Calculat类:用于计算余弦相似度:
getDict(List<String> originalText, List<String> contrastText)方法:通过将originalText,contrastTest中的词合并成一个集合,用于计算词频。
getWordFrequency(List<String> text)方法:计算集合中各个词的词频,并返回。
getCosine(List<String> originalText,List<String> contrastText)方法:计算两篇文章的相似度并返回。
4、函数关系:

5、关键函数:
余弦相似度的算法很简单,就是数学计算。所以最关键的是怎么计算词频。
计算词频的方法:通过将分词后的list集合添加进map集合中,key值为词,value为下标从0开始,然后创建长为map.size()的数组,遍历分词后的list集合,如果词语在map集合中,取出value值,value值对应数组下标,该位置的数组值加一。
- 算法流程
![]()
四、接口部分的性能改进
1、使用SonarLint插件改进代码质量
通过这个插件进行扫描,将整个项目中代码不合理,有漏洞的代码全部展示出来,并且会有相对应的解决方案,代码示例,通过阅读警告说明和解决方案,一个个解决漏洞。
改进后没有警告

2、使用JProfiler分析
- 性能分析图:
*类的内存消耗
- CUP Load (运行时间1.1s,符合要求)
![]()
- 堆内存
![]()
- 程序中消耗最大的方法
![]()
从图中可以看出是getCosine()方法
![]()
- CUP Load (运行时间1.1s,符合要求)
五、单元测试展示
- 代码
![]()
说明:测试的数据包含样本数据和自己设计的数据,自身添加的文件有一个空文件,四个只有一个句子的文件。通过调用getAnswer()方法对文件进行查重可以测试所有的方法。 - 测试结果:
![]()
![]()
解释:因为第一个是空文件,所以会抛出空文本异常,接下来的是样本文件,最后的几个文件是自定义的短句文件。 - 测试覆盖率:
![]()
六、异常处理
NullFileException:空文件异常,当文件为空时就没有比较的必要性。当读取的文件为空时,就产生异常。
异常设计:

异常测试:












浙公网安备 33010602011771号