java实现论文查重
| 作业所属课程 | 计科21级12班软件工程 |
|---|---|
| 作业要求 | 个人项目:论文查重 |
| 作业链接 | 第一个个人项目 |
| 作业目标 | 实现论文查重,并优化代码,提高性能 |
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 60 | 120 |
| Estimate | 估计这个任务需要多少时间 | 20 | 20 |
| Development | 开发 | 100 | 120 |
| Analysis | 需求分析(包括学习新技术) | 120 | 240 |
| Design Spec | 生成设计文档 | 30 | 30 |
| Design Review | 设计复审 | 20 | 20 |
| Coding Standard | 代码规范(为目前的开发制定合适的规范) | 40 | 40 |
| Design | 具体设计 | 120 | 60 |
| Coding | 具体编码 | 120 | 180 |
| Code Review | 代码复审 | 60 | 60 |
| Test | 测试(自我测试,修改代码,提交修改) | 100 | 240 |
| Reporting | 报告 | 200 | 240 |
| Test Repor | 测试报告 | 60 | 120 |
| Size Measurement | 计算工作量 | 30 | 30 |
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
| 合计 | 1110 | 1550 | |
核心算法:
simhash+海明距离
simhash
分为以下几个步骤:
1.分词:通过外部的jar包分词器IKAnalysis 进行智能分词
2.计算hash值:通过hash函数对每个划分的词计算出相应的hash值,
3.加权:计算词频赋予权重并运算
4.合并:将所有词的加权hash值相加
5.降维:将计算后的序列串变为01串
海明距离
将两个文本中出现的词进行交集和并集运算,交集的大小与并集的大小之商就是海明距离
模块接口的设计与实现
工程结构图

源代码放在com.rjgc01包下,包含三个类
其中main类作为程序的入口,读写文件的方法都在main类中;
SimHash类把文本分词,并分词,计算hash值,加权,合并;
Hamming类计算海明距离
SimHash部分代码
public static String getHash(String s){
try {
//使用MD5获得hash值
MessageDigest messageDigest=MessageDigest.getInstance("MD5");
return new BigInteger(1,messageDigest.digest(s.getBytes("UTF-8"))).toString(2);
} catch (Exception e) {
e.printStackTrace();
return s;
}
}
//获得SimHash
//map存放的是词,以及频数
public static String getSimHash(Map<String,Integer> map) {
int []temp=new int[128];
for (String s : map.keySet()) {
String hash = getHash(s);
//如果hash码不够128位,补齐0
if (hash.length()<128)
{
int bit=128-hash.length();
for (int i=0;i<bit;i++)
hash+="0";
}
//加权,把频数乘以hash,同时合并
for (int j=0;j<temp.length;j++)
{
if (hash.charAt(j)=='1')
{
temp[j] += map.get(s);
}
else
temp[j]-=map.get(s);
}
}
String str="";
for (int i=0;i< temp.length;i++) {
if (temp[i]>0) str+="1"; else str+="0";
}
return str;
}
Hamming类部分代码
public static int getHammingDistance(String simHash1,String simHash2) {
int distance=0;
for (int i=0;i<simHash1.length();i++)
{
if (simHash1.charAt(i)!=simHash2.charAt(i))
distance++;
}
return distance;
}
public static double getSimilarity(String simHash1,String simHash2) {
int hammingDistance = HammingDistance.getHammingDistance(simHash1, simHash2);
return 0.01*(100-hammingDistance*100/128);
}
模块接口部分的性能改进
实时内存-各个对象
其中分词和分词存储占用了大多数内存

堆内存的占用情况

模块部分单元测试展示
main类测试
String s1="e:\\TestText\\orig.txt";
String s2="e:\\TestText\\orig_0.8_add.txt";
String s3="e:\\TestText\\output.txt";
String s4="e:\\TestText\\orig_0.8_del.txt";
String s5="e:\\TestText\\orig_0.8_dis_1.txt";
String s6="e:\\TestText\\orig_0.8_dis_10.txt";
String s7="e:\\TestText\\orig_0.8_dis_15.txt";
//测试代码的正确运行
@Test
public void main() {
main.ReadFile(s1,s2,s3);
}
//测试代码为空
@Test
public void testIsNull()
{
main.ReadFile(null,s2,s3);
}
//写入的路径错误
@Test
public void testRouteMistakeOut() {
main.ReadFile(s1,s2,s3+"abc");
}
//读入的路径错误
@Test
public void testRouteMistakeIn() {
main.ReadFile(s1+"abc",s2,s3);
}
//两份写入文件相同
@Test
public void testTheSameReadRoute() {
main.ReadFile(s2,s2,s3);
}
//orig_0.8_add.txt
@Test
public void testAdd() {
main.ReadFile(s1,s2,s3);
}
//orig_0.8_del.txt
@Test
public void testDel() {
main.ReadFile(s1,s4,s3);
}
//orig_0.8_dis_1.txt
@Test
public void testDis1() {
main.ReadFile(s1,s5,s3);
}
//orig_0.8_dis_10.txt
@Test
public void testDis10() {
main.ReadFile(s1,s6,s3);
}
//orig_0.8_dis_15.txt
@Test
public void testDis15() {
main.ReadFile(s1,s7,s3);
}
测试结果



代码覆盖率

模块部分异常处理说明


浙公网安备 33010602011771号