Java利用hanlp完成语句相似度分析的案例详解
分享一篇hanlp分词工具使用的小案例,即利用hanlp分词工具分析两个中文语句的相似度的案例。供大家一起学习参考!
在做考试系统需求时,后台题库系统提供录入题目的功能。在录入题目的时候,由于题目来源广泛,且参与录入题目的人有多位,因此容易出现录入重复题目的情况。所以需要实现语句相似度分析功能,从而筛选出重复的题目并人工处理之。
下面介绍如何使用Java实现上述想法,完成语句相似度分析:
1、使用HanLP完成分词:
首先,添加HanLP的依赖:(jsoup是为了处理题干中的html标签,去除html标签得到纯文本的题干内容)

分词代码如下,需要处理html标签和标点符号:
private static List<String> getSplitWords(String sentence) {
// 去除掉html标签
sentence = Jsoup.parse(sentence.replace(" ","")).body().text();
// 标点符号会被单独分为一个Term,去除之
return HanLP.segment(sentence).stream().map(a -> a.word).filter(s -> !"`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、? ".contains(s)).collect(Collectors.toList());
}
2、合并分词结果,列出所有的词:

3、统计词频,得到词频构成的向量:
代码如下,其中allWords是上一步中得到的所有的词,sentWords是第一步中对单个句子的分词结果:

4、计算相似度(两个向量的余弦值):

以上所有方法的完整代码如下,使用SimilarityUtil.getSimilarity(String s1,String s2)即可得到s1和s2的语句相似度:
package com.yuantu.dubbo.provider.questionRepo.utils;
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.dictionary.CustomDictionary;
import org.jsoup.Jsoup;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class SimilarityUtil {
static {
CustomDictionary.add("子类");
CustomDictionary.add("父类");
}
private SimilarityUtil() {
}
/**
* 获得两个句子的相似度
*
* @param sentence1
* @param sentence2
* @return
*/
public static double getSimilarity(String sentence1, String sentence2) {
List<String> sent1Words = getSplitWords(sentence1);
System.out.println(sent1Words);
List<String> sent2Words = getSplitWords(sentence2);
System.out.println(sent2Words);
List<String> allWords = mergeList(sent1Words, sent2Words);
int[] statistic1 = statistic(allWords, sent1Words);
int[] statistic2 = statistic(allWords, sent2Words);
double dividend = 0;
double divisor1 = 0;
double divisor2 = 0;
for (int i = 0; i < statistic1.length; i++) {
dividend += statistic1[i] * statistic2[i];
divisor1 += Math.pow(statistic1[i], 2);
divisor2 += Math.pow(statistic2[i], 2);
}
return dividend / (Math.sqrt(divisor1) * Math.sqrt(divisor2));
}
private static int[] statistic(List<String> allWords, List<String> sentWords) {
int[] result = new int[allWords.size()];
for (int i = 0; i < allWords.size(); i++) {
result[i] = Collections.frequency(sentWords, allWords.get(i));
}
return result;
}
private static List<String> mergeList(List<String> list1, List<String> list2) {
List<String> result = new ArrayList<>();
result.addAll(list1);
result.addAll(list2);
return result.stream().distinct().collect(Collectors.toList());
}
private static List<String> getSplitWords(String sentence) {
// 去除掉html标签
sentence = Jsoup.parse(sentence.replace(" ","")).body().text();
// 标点符号会被单独分为一个Term,去除之
return HanLP.segment(sentence).stream().map(a -> a.word).filter(s -> !"`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、? ".contains(s)).collect(Collectors.toList());
}
}
---------------------
Java利用hanlp完成语句相似度分析的案例详解的更多相关文章
- 《java入门第一季》之面向对象(面向对象案例详解)
通过几个小案例理重新回顾一下前面所写的内容,对面向对象的理解更加深刻的目的: 案例一: /* 需求: 定义一个员工类,自己分析出几个成员, 然后给出成员变量,构造方法,getXxx()/setXxx( ...
- Android Telephony分析(二) ---- RegistrantList详解
前言 本文主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程.在Telephony模块中,在RIL.Tracker(ServiceStateTrac ...
- 《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)
1.简介 从这一篇开始介绍和分享Java+Selenium+POM的简单自动化测试框架设计.第一个设计点,就是支持跨浏览器测试. 宏哥自己认为的支持跨浏览器测试就是:同一个测试用例,支持用不同浏览器去 ...
- 提高Java代码质量的Eclipse插件之Checkstyle的使用详解
提高Java代码质量的Eclipse插件之Checkstyle的使用详解 CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具.它能够自动化代 ...
- 【集合框架】JDK1.8源码分析之ArrayList详解(一)
[集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...
- Java集合中List,Set以及Map等集合体系详解
转载请注明出处:Java集合中List,Set以及Map等集合体系详解(史上最全) 概述: List , Set, Map都是接口,前两个继承至collection接口,Map为独立接口 Set下有H ...
- java 日志体系(三)log4j从入门到详解
java 日志体系(三)log4j从入门到详解 一.Log4j 简介 在应用程序中添加日志记录总的来说基于三个目的: 监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作: 跟踪代 ...
- 利用Intellij+MAVEN搭建Spring+Mybatis+MySql+SpringMVC项目详解
http://blog.csdn.net/noaman_wgs/article/details/53893948 利用Intellij+MAVEN搭建Spring+Mybatis+MySql+Spri ...
- Android Telephony分析(五) ---- TelephonyRegistry详解
本文紧接着上一篇文章<Android Telephony分析(四) —- TelephonyManager详解 >的1.4小节.从TelephonyRegistry的大部分方法中: 可以看 ...
随机推荐
- django面试题必问
1.谈谈你对http协议的认识. HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议.它可以使浏览器更加高效,使 ...
- JSON的学习,希望可以指导
1.JSON的介绍 是一种轻量级的数据交换格式.简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言. 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率. 2.格式 JSON ...
- POJ2777-Count Color (线段树)
题目传送门:http://poj.org/problem?id=2777 Count Color Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
- Linux命令学习之路——变更工作目录:cd
使用权限:所有角色 使用方式:cd [ targetDir ] 作用:该命令用于在Linux中切换工作目录 注意点: 1.targetDir代表目标目录,可以采用绝对路径或相对路径表示: 2.当tar ...
- 怎样用CMD命令强行删除文件?
如果你要删除的整个文件夹以及文件夹里面的所有内容的话rd/s/q 盘符:\某个文件夹 (这样整个文件夹所有的文件和文件夹都删除了)比如我想删除D盘的123文件夹以及123文件夹里面所有的内容rd/ ...
- Map集合与转化
|--Hashtable:底层是哈希表数据结构,是线程同步的.不可以存储null键,null值. |--HashMap:底层是哈希表数据结构,是线程不同步的.可以存储null键,null值.替代了Ha ...
- 数据结构HUFFman求权值
#include <bits/stdc++.h>using namespace std;priority_queue< int, vector <int>, greate ...
- 环境变量、cp、mv、cat 等命令
1.环境变量: PATH 个人理解 环境变量,即是所有命令文件所存放的目录,或是人为的定义的目录,(命令文件所存放的目录,当输入一个命令的时候,系统会自动找到且不报错,并不需要输入绝对路径,来运行相关 ...
- if-else练习
练习1 import java.util.Scanner; public class V{ public static void main(String[] args){ Scanner s=new ...
- ELFhash
字符串哈希算法(以ELFHash详解) 更多字符串哈希算法请参考:http://blog.csdn.net/AlburtHoffman/article/details/19641123 先来了解一 ...