Java Apache Jaccard文本相似度匹配初体验

文章目录

  • 前言
  • 一、文本相似度算法的选择
  • 二、常见的文本相似度算法介绍
  • 三、使用示例
    • 1、引入jar包
    • 2、方法示例
    • 3、Jaccard源码剖析
    • 4、Jaccard源码解释
  • 写在最后


前言

产品今天提了个需求,大概是这样的,来,请看大屏幕。。。额。。。搞错了,重来!来,请看需求原型
需求原型描述
需求原型清晰明了,就不做过多解释了


一、文本相似度算法的选择

文本相似度其实很好理解,按照字面意思,就是两个字符串比较,根据一定的规则来返回两个字符串的相似度。
按照需求来说的话,我需要的只是文本的匹配,对于准确性的要求可能没有那么高,所以,这里选择Apache Jaccard的算法就能满足需求

二、常见的文本相似度算法介绍

1.Levenshtein距离: Levenshtein距离算法在计算字符串相似度时需要考虑所有的插入、删除和替换操作,因此对于长字符串来说,时间复杂度较高。然而,这个算法比较准确,能够捕捉到字符串间的细微差异。(后面只会说一下调用示例,不会过重说明)

2.Jaccard相似度:Jaccard相似度算法计算集合的交集和并集的比值,是一种基本的相似度度量。它对字符串长度不敏感,计算速度相对较快。但是,它对于字符顺序不敏感,并且只考虑字符出现与否,而不考虑出现的频率。 (这里着重说明一下)

3.Cosine相似度: Cosine相似度算法将字符串视为向量,并计算它们的夹角余弦值。这个算法在计算文本相似度时,考虑了字符的频率和顺序。它也适用于处理较长的字符串,但在比较两个字符串之间的相似度时,需要先将其向量化,因此相对复杂一些。(其实Cosine相似度我也看了下源码,也度娘了一下其中的原理,由于个人数学不好,看到一大串的数学公式,感觉头都大了,就没深究^ o ^。感兴趣的同学可以自行度娘,并深入研究一下 )

三、使用示例

1、引入jar包

Levenshtein、Jaccard和Cosine都是 Apache公司的,所以引入一个就可以了

	<dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-text</artifactId>
       <version>1.10.0</version>
    </dependency>

2、方法示例

Jaccard相似度: 用于计算两个集合之间的相似度,可以将字符串视为字符的集合,计算它们的交集和并集的比值。Jaccard相似度的取值范围是01,值越接近1表示相似度越高。
Jaccard示例如下:

import org.apache.commons.text.similarity.JaccardSimilarity;
 // Jaccard文本相似度
public static void main(String[] args) {
    String str1 = "收到钢化膜其中一张破裂+收到钢化膜其中一张破裂要求补发一张+3191";
    String str2 = "收到后钢化膜有一张碎了角+收到后钢化膜有一张碎了角,请补发+3191";
        
    // Jaccard匹配文本相似度
    JaccardSimilarity jacc = new JaccardSimilarity();
    Double jaccardSimilarity = jacc.apply(str1, str2);
    System.out.println("Jaccard===>文本相似度:" + jaccardSimilarity);
}

Jaccard计算结果:
Jaccard计算结果

Levenshtein距离示例如下:
Levenshtein距离:也称为编辑距离,用于计算两个字符串之间的最小编辑操作次数(插入、删除、替换)来转换一个字符串为另一个字符串。编辑距离越小,表示两个字符串越相似。

import org.apache.commons.text.similarity.JaccardSimilarity;
 // Jaccard文本相似度
public static void main(String[] args) {
    String str1 = "收到钢化膜其中一张破裂+收到钢化膜其中一张破裂要求补发一张+3191";
    String str2 = "收到后钢化膜有一张碎了角+收到后钢化膜有一张碎了角,请补发+3191";
        
    int distance = LevenshteinDistance.getDefaultInstance().apply(str1, str2);
	double levenshteinSimilarity= 1 - (double) distance / Math.max(str1.length(), str2.length());
    System.out.println("Levenshtein===>文本相似度:" + levenshteinSimilarity);
}

Levenshtein计算结果:
Levenshtein距离计算结果


3、Jaccard源码剖析

import org.apache.commons.text.similarity.JaccardSimilarity;

public static void main(String[] args) {
    String str1 = "收到钢化膜其中一张破裂+收到钢化膜其中一张破裂要求补发一张+3191";
    String str2 = "收到后钢化膜有一张碎了角+收到后钢化膜有一张碎了角,请补发+3191";

    int leftLength = str1.length();
    int rightLength = str2.length();
    if (leftLength == 0 && rightLength == 0) {
        System.out.println("文本相似度:" + 1.0);
    } else if (leftLength != 0 && rightLength != 0) {
        Set<Character> leftSet = new HashSet();
        for (int i = 0; i < leftLength; ++i) {
            leftSet.add(str1.charAt(i));
         }
        System.out.println("leftSet内容:" + JSONObject.toJSONString(leftSet));
        System.out.println("leftSet的Size:" + leftSet.size());

        Set<Character> rightSet = new HashSet();
        for (int i = 0; i < rightLength; ++i) {
             rightSet.add(str2.charAt(i));
        }
        System.out.println("rightSet内容:" + JSONObject.toJSONString(rightSet));
        System.out.println("rightSet的Size:" + rightSet.size());

        Set<Character> unionSet = new HashSet(leftSet);
        unionSet.addAll(rightSet);
        System.out.println("unionSet内容:" + JSONObject.toJSONString(unionSet));
        System.out.println("unionSet的Size:" + unionSet.size());

        int intersectionSize = leftSet.size() + rightSet.size() - unionSet.size();
        System.out.println("intersectionSize的Size:" + intersectionSize);

        double calRes = 1.0 * (double) intersectionSize / (double) unionSet.size();
        System.out.println("文本相似度:" + calRes);
  	} else {
        System.out.println("文本相似度:" + 0.0);
    }
}

4、Jaccard源码解释

该函数用于计算两个字符串的文本相似度。使用字符集来表示字符串,并计算两个字符串的交集和并集,然后根据交集和并集的大小计算相似度。具体步骤如下:

  1. 初始化两个字符串str1和str2。
  2. 计算两个字符串的长度,分别保存在leftLength和rightLength变量中。
  3. 如果两个字符串长度都为0,则输出相似度为1.0。
  4. 如果两个字符串长度都不为0,则进行以下操作:
    a. 创建一个字符集leftSet,将str1中的每个字符添加到leftSet中。
    b. 输出leftSet的内容和大小。
    c. 创建一个字符集rightSet,将str2中的每个字符添加到rightSet中。
    d. 输出rightSet的内容和大小。
    e. 创建一个字符集unionSet,并将leftSet中的元素复制到unionSet中。
    f. 将rightSet中的元素添加到unionSet中。
    g. 输出unionSet的内容和大小。
    h. 计算交集的大小:intersectionSize = leftSet的大小 + rightSet的大小 - unionSet的大小。
    i. 计算相似度:calRes = (double) intersectionSize / (double) unionSet的大小。
    j. 输出相似度。
  5. 如果两个字符串长度不一致,则输出相似度为0.0。

写在最后

最佳算法的选择取应取决于实际应用中具体情况和要求,同时需要考虑多个方面,如算法的复杂度、字符串长度、算法的适用性、是否需要分词等等。
如果仅仅是需要计算几个短字符串之间的相似度,Jaccard相似度可能会是一个好的选择。
如果是需要捕捉字符串细微的差异并进行较高精度的匹配,Levenshtein距离可能会更合适。
如果需要处理的是文本数据Cosine相似度可能是更好的选择。
此外,如果需要对于大规模的字符串匹配需求(如搜索引擎),更复杂的算法(如基于索引的搜索算法)可能会有更适合的算法。

原创不易,望一键三连 (^ _ ^)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/669235.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系统思考—思考快与慢

“膝反射思考做决策&#xff0c;你的公司能走多远&#xff1f;” 在快节奏的商业环境中&#xff0c;我们的大脑往往默认采用“快速直觉反应”模式来做决策&#xff0c;这种方式节省能量&#xff0c;属于我们认知的“系统一”。然而&#xff0c;仅依靠直觉反应&#xff0c;即所…

go中的指针详解

因为大一的时候c语言没学好,所以看到指针很心烦 ,后来速成了一遍go ,每每写道指针部分就开始遗忘 ,所以专门对指针部分做了此笔记 概念 在 Go 语言中&#xff0c;指针是一种变量类型&#xff0c;它存储的是另一个变量的内存地址。通过指针&#xff0c;你可以访问和修改它指向…

数据结构——经典链表OJ(二)

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 点击主页&#xff1a;optimistic_chen和专栏&#xff1a;c语言&#xff0c; 创作不易&#xff0c;大佬们点赞鼓…

认识JAVA中的异常

目录&#xff1a; 一. 异常概念与体系结构 二. 异常的处理 三. 自定义异常类 一. 异常概念与体系结构: 1 异常的概念:在 Java 中&#xff0c;将程序执行过程中发生的 不正常行为 称为异常&#xff0c; 如&#xff1a;算数异常&#xff1a; ArithmeticException System.out.pri…

数据结构-堆(带图)详解

前言 本篇博客我们来仔细说一下二叉树顺序存储的堆的结构&#xff0c;我们来看看堆到底如何实现&#xff0c;以及所谓的堆排序到底是什么 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;数据结构_普通young man的博客-CSDN博客 若有问题 评…

Triton TensorRT-LLM

Deploy an AI Coding Assistant with NVIDIA TensorRT-LLM and NVIDIA Triton | NVIDIA Technical Blog 模型格式先转为FasterTransformer&#xff1b;再用TensorRT-LLM将其compile为TensorRT格式&#xff1b;然后可用TensorRT-LLM来跑推理&#xff08;或者模型放到Triton Rep…

前端最新面试题(基础模块HTML/CSS/JS篇)

目录 一、HTML、HTTP、WEB综合问题 1 前端需要注意哪些SEO 2 img的title和alt有什么区别 3 HTTP的几种请求方法用途 4 从浏览器地址栏输入url到显示页面的步骤 5 如何进行网站性能优化 6 HTTP状态码及其含义 7 语义化的理解 8 介绍一下你对浏览器内核的理解? 9 html…

【数据挖掘】3σ原则识别数据中的异常值(附代码)

写在前面&#xff1a; 首先感谢兄弟们的订阅&#xff0c;让我有创作的动力&#xff0c;在创作过程我会尽最大能力&#xff0c;保证作品的质量&#xff0c;如果有问题&#xff0c;可以私信我&#xff0c;让我们携手共进&#xff0c;共创辉煌。 路虽远&#xff0c;行则将至&#…

生态系统服务功能之碳储量

大家好&#xff0c;这期开始新生态系统服务功能即碳储量的计算&#xff0c;这部分较简单&#xff0c;下面让我们开始吧&#xff01;&#xff01;&#xff01; 碳储量的计算公式 生态系统通过从大气中释放和吸收二氧化碳等温室气体来调节地球气候&#xff0c;而森林、 草原和沼…

论文作图之高压缩比导出PDF

笔者使用Adobe Illustrator 2023创建可编辑pdf图&#xff0c;按照默认的导出设置保存pdf文件时&#xff0c;得到的图存储很大。为了解决存储过大且还保留一定编辑功能的问题&#xff0c;作者实践出了一种导出pdf的设置方法。 首先在AI中点击文件->存储为&#xff0c;点击保…

【Java】面向对象的三大特征:封装、继承、多态

封装 什么叫封装&#xff1f; 在我们写代码的时候经常会涉及两种角色&#xff1a; 类的实现者 和 类的调用者。 封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的&#xff0c; 只要知道如何使用类就行了&#xff0c;这样就降低了类使用者的学习和使用成本&a…

民国漫画杂志《时代漫画》第39期.PDF

时代漫画39.PDF: https://url03.ctfile.com/f/1779803-1248636473-6bd732?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

问界新M7 Ultra仅售28.98万元起,上市即交付

5月31日&#xff0c;问界新M7 Ultra正式上市。发布会上&#xff0c;鸿蒙智行旗下多款产品交出最新答卷——问界新M5上市1个月大定突破2万台&#xff1b;智界S7位列30万纯电轿车4月交付量NO.3&#xff1b;问界M9上市5个月大定突破9万台。其中&#xff0c;作为中国高端豪华SUV市场…

【Linux】日志管理

一、日志进程 1、处理日志的进程 rsyslogd&#xff1a;系统专职日志程序 观察rsyslogd程序&#xff1a; ps aux | grep rsyslogd 2、常见的日志文件 1、系统主日志文件: /var/log/messages 动态查看日志文件尾部&#xff1a; tail -f /var/log/messages 2、安全…

车载软件架构 - AP AUTOSAR 设计思想及原理

车载软件架构 - AP AUTOSAR 设计思想及原理 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消…

SpringAdminClient如何将Httpbasic账号密码告知SpringAdminServer

场景&#xff0c;因为Config Service开了权限校验&#xff0c;注册到eureka之后&#xff0c;SpringAdmin查看信息会报错401&#xff0c;如果想在SpringAdmin中正确的看到Config Service的actuator信息则需要将账号密码告知给SpringAdmin&#xff0c;磁力用的是Eureka作为发现服…

泄漏libc基地址

拿libc基地址 方法一&#xff1a;格式化字符串 格式化字符串&#xff0c;首先确定输入的 AAAA 在栈上的位置&#xff08;x&#xff09;。使用 elf.got[fun] 获得got地址。利用格式化字符串&#xff0c;构造payload泄漏got地址处的值&#xff0c;recv接受到的字符串中&#xf…

力扣之链表专题

1. (LeetCode-21)合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 …

AIGC绘画设计——midjourney有哪些好用的关键词?

midjourney有哪些高级关键词&#xff1f; 这一期继续分享一些高级的关键词&#xff0c; 我有一些案例也是从其他博主那学习来的&#xff0c; 但为了尽可能不出错&#xff0c;每个案例都是自己尝试了很多次后才拿出来的。 挑选了几个效果比较好&#xff0c;使用场景较高的类型…

牛客NC164 最长上升子序列(二)【困难 贪心+二分 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/4af96fa010c44638a7e112abf65f7237 思路 贪心二分 所谓贪心&#xff0c;就是往死里贪&#xff0c;所以对于最大上升子序列&#xff0c;结尾元素越小&#xff0c;越有利于后面接上其他的数&#xff0c;也就可能变…