java实现论文查重

作业所属课程 计科21级12班软件工程
作业要求 个人项目:论文查重
作业链接 第一个个人项目
作业目标 实现论文查重,并优化代码,提高性能

Github链接

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);
    }

测试结果



 

代码覆盖率

模块部分异常处理说明

posted @ 2023-09-15 11:09  2021计科2班许志楷  阅读(129)  评论(0)    收藏  举报