java like a_如何在Java中实现类似“ LIKE”运算符的SQL?

我需要Java中的比较器,该比较器的语义与sql"赞"运算符相同。

例如:

myComparator.like("digital","%ital%");

myComparator.like("digital","%gi?a%");

myComparator.like("digital","digi%");

应该评估为真,并且

myComparator.like("digital","%cam%");

myComparator.like("digital","tal%");

应该评估为假。 关于如何实现这样的比较器的任何想法,或者有人知道具有相同语义的实现吗? 可以使用正则表达式吗?

请参阅Apache Cayenne项目中的RegexUtil#sqlPatternToRegex(String)。

。*将匹配正则表达式中的任何字符

我认为Java语法是

"digital".matches(".*ital.*");

对于单个字符匹配,只需使用单个点。

"digital".matches(".*gi.a.*");

为了匹配实际的点,请将其转为斜线点

\.

是的,谢谢!但是,如果单词inst如此简单,例如"%dig%",并且字符串需要一些escping键?已经有东西了吗?怎么样 ? ?

我为问号运算符编辑了答案。我对您的其余评论感到有些困惑。您是说要使用sql语法显示字符串,并且要按原样对其求值?如果是这种情况,我认为您将需要手动替换为sql语法。

如果用作搜索模式的字符串也包含诸如(或)的分组字符怎么办?其他字符怎么需要转义?

我认为这取决于您允许多少选择。

只是要注意。*是贪婪的(。*?可能更合适)。我不认为正则表达式中的。*与SQL中的%语义完全相同。

很好,请参阅以下问题进行爆炸stackoverflow.com/questions/255815/

是的,可以使用正则表达式来完成。请记住,Java的正则表达式与SQL的" like"具有不同的语法。而不是" %",您将拥有" .*",而不是" ?",您将拥有" ."。

使它有些棘手的是,您还必须转义Java视为特殊字符的任何字符。由于您正试图使它类似于SQL,所以我猜^$[]{}\不应该出现在正则表达式字符串中。但是在进行任何其他替换之前,您必须将" ."替换为" \\."。 (编辑:Pattern.quote(String)通过用" \Q"和" \E"括起字符串来转义所有内容,这将使表达式中的所有内容都被视为文字(根本没有通配符)。因此,您绝对不会不想使用它。)

此外,正如Dave Webb所说,您还需要忽略大小写。

考虑到这一点,下面是其外观示例:

public static boolean like(String str, String expr) {

expr = expr.toLowerCase(); // ignoring locale for now

expr = expr.replace(".","\\."); //"\" is escaped to"" (thanks, Alan M)

// ... escape any other potentially problematic characters here

expr = expr.replace("?",".");

expr = expr.replace("%",".*");

str = str.toLowerCase();

return str.matches(expr);

}

是否存在一种方法,可以在Java正则表达式中转义具有特殊含义的每个字符?

是的,Pattern.quote(java.sun.com/javase/6/docs/api/java/util/regex/)可以做到。出于某种原因,我认为这可能会导致问题,但是现在我不知道为什么不将其包括在答案中。

哦,是的,现在我记得了。这是因为 ?是一个特殊的正则表达式字符,因此在替换它之前将其转义。我想我们可以改为使用Pattern.quote,然后使用expr = expr.replace(" \?","。");

第三行应显示为replace(".","\\.");

你是对的。我应该在发布之前先在点上对其进行测试。

您还可以添加expr = expr.replaceAll("(?,因为"\_"可以在SQL中转义,因此在这种情况下不应替换为"."。 (对于一个字符,我使用了_而不是?。)

另外,对于%,此替换会更好:expr = expr.replaceAll("(?

正则表达式是最通用的。但是,某些LIKE函数可以不使用正则表达式而形成。例如

String text ="digital";

text.startsWith("dig"); // like"dig%"

text.endsWith("tal"); // like"%tal"

text.contains("gita"); // like"%gita%"

我可以找到的每个SQL参考都说"任何单个字符"通配符是下划线(_),而不是问号(?)。因为下划线不是正则表达式元字符,所以这简化了一些事情。但是,由于mmyers给出的原因,您仍然不能使用Pattern.quote()。当我以后想编辑正则表达式时,这里还有另一种转义正则表达式的方法。这样,like()方法变得非常简单:

public static boolean like(final String str, final String expr)

{

String regex = quotemeta(expr);

regex = regex.replace("_",".").replace("%",".*?");

Pattern p = Pattern.compile(regex,

Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

return p.matcher(str).matches();

}

public static String quotemeta(String s)

{

if (s == null)

{

throw new IllegalArgumentException("String cannot be null");

}

int len = s.length();

if (len == 0)

{

return"";

}

StringBuilder sb = new StringBuilder(len * 2);

for (int i = 0; i < len; i++)

{

char c = s.charAt(i);

if ("[](){}.*+?$^|#\".indexOf(c) != -1)

{

sb.append("\");

}

sb.append(c);

}

return sb.toString();

}

如果您真的想对通配符使用?,那么最好的选择是在quotemeta()方法中将其从元字符列表中删除。替换其转义的格式replace("\\?",".")并不安全,因为原始表达式中可能存在反斜杠。

这给我们带来了真正的问题:大多数SQL风格似乎都支持[a-z]和[^j-m]或[!j-m]形式的字符类,并且它们都提供了一种转义通配符的方法。后者通常是通过ESCAPE关键字完成的,该关键字使您每次都可以定义一个不同的转义符。可以想象,这使事情复杂化了很多。转换为正则表达式可能仍然是最好的选择,但是解析原始表达式会更加困难-实际上,您要做的第一件事就是形式化LIKE表达式本身的语法。

是的,你是对的。我比我更喜欢您的解决方案。

如果(s == null)抛出新的IllegalArgumentException("字符串不能为null");否则if(s.isEmpty())返回";

要在Java中实现sql的LIKE函数,您不需要在

它们可以通过以下方式获得:

String text ="apple";

text.startsWith("app"); // like"app%"

text.endsWith("le"); // like"%le"

text.contains("ppl"); // like"%ppl%"

这本质上只是多年前发布的现有答案的重复。

该答案已经发布

您可以将'%string%'更改为contains(),将'string%'更改为startsWith(),将'%string"'更改为endsWith()。

您还应该在字符串和模式上同时运行toLowerCase(),因为LIKE是区分大小写的。

除了使用正则表达式外,不确定如何处理'%string%other%'。

如果您使用正则表达式:

在替换%字符之前,请给字符串加引号

注意LIKE字符串中的转义字符

什么是abot"%this%string%"?分割%符号,遍历数组,然后检查每个条目?我认为这可以做得更好...

public static boolean like(String toBeCompare, String by){

if(by != null){

if(toBeCompare != null){

if(by.startsWith("%") && by.endsWith("%")){

int index = toBeCompare.toLowerCase().indexOf(by.replace("%","").toLowerCase());

if(index < 0){

return false;

} else {

return true;

}

} else if(by.startsWith("%")){

return toBeCompare.endsWith(by.replace("%",""));

} else if(by.endsWith("%")){

return toBeCompare.startsWith(by.replace("%",""));

} else {

return toBeCompare.equals(by.replace("%",""));

}

} else {

return false;

}

} else {

return false;

}

}

可能会帮助你

http://josql.sourceforge.net/具有您所需要的。查找org.josql.expressions.LikeExpression。

Apache Cayanne ORM具有"内存中的评估"

它可能不适用于未映射的对象,但看起来很有希望:

Expression exp = ExpressionFactory.likeExp("artistName","A%");

List startWithA = exp.filterObjects(artists);

您知道休眠是否支持此功能吗?我的意思是,使用这样的表达式过滤当前内存中的对象?

Java字符串具有.startsWith()和.contains()方法,它们将使您获得更多收益。对于更复杂的事情,您必须使用正则表达式或编写自己的方法。

比较器和可比较接口在这里可能不适用。它们处理排序,并返回符号或0的整数。您的操作是查找匹配项,并返回true / false。那不一样。

欢迎您为运营商建议一个更好的名称。我不喜欢批评家,没有改进的建议,顺便说一句。

我不完全了解贪婪的问题,但是如果它对您有用,请尝试以下操作:

public boolean like(final String str, String expr)

{

final String[] parts = expr.split("%");

final boolean traillingOp = expr.endsWith("%");

expr ="";

for (int i = 0, l = parts.length; i < l; ++i)

{

final String[] p = parts[i].split("\\\\\\?");

if (p.length > 1)

{

for (int y = 0, l2 = p.length; y < l2; ++y)

{

expr += p[y];

if (i + 1 < l2) expr +=".";

}

}

else

{

expr += parts[i];

}

if (i + 1 < l) expr +="%";

}

if (traillingOp) expr +="%";

expr = expr.replace("?",".");

expr = expr.replace("%",".*");

return str.matches(expr);

}

您的内部split()和循环会替换任何?带点的顺序-我不明白。为什么要选择该序列,而只用一个点代替它,就像一个单独的问号?

它取代了?与。因为?是单个任意字符的占位符。我知道 \\\?看起来很奇怪,但是我进行了测试,并且对于我的测试来说似乎可行。

public static boolean like(String source, String exp) {

if (source == null || exp == null) {

return false;

}

int sourceLength = source.length();

int expLength = exp.length();

if (sourceLength == 0 || expLength == 0) {

return false;

}

boolean fuzzy = false;

char lastCharOfExp = 0;

int positionOfSource = 0;

for (int i = 0; i < expLength; i++) {

char ch = exp.charAt(i);

// 是否转义

boolean escape = false;

if (lastCharOfExp == '\') {

if (ch == '%' || ch == '_') {

escape = true;

// System.out.println("escape" + ch);

}

}

if (!escape && ch == '%') {

fuzzy = true;

} else if (!escape && ch == '_') {

if (positionOfSource >= sourceLength) {

return false;

}

positionOfSource++;// <<

} else if (ch != '\') {// 其他字符,但是排查了转义字符

if (positionOfSource >= sourceLength) {// 已经超过了source的长度了

return false;

}

if (lastCharOfExp == '%') { // 上一个字符是%,要特别对待

int tp = source.indexOf(ch);

// System.out.println("上一个字符=%,当前字符是=" + ch +",position=" + position +",tp=" + tp);

if (tp == -1) { // 匹配不到这个字符,直接退出

return false;

}

if (tp >= positionOfSource) {

positionOfSource = tp + 1;// <<

if (i == expLength - 1 && positionOfSource < sourceLength) { // exp已经是最后一个字符了,此刻检查source是不是最后一个字符

return false;

}

} else {

return false;

}

} else if (source.charAt(positionOfSource) == ch) {// 在这个位置找到了ch字符

positionOfSource++;

} else {

return false;

}

}

lastCharOfExp = ch;// <<

// System.out.println("当前字符是=" + ch +",position=" + position);

}

// expr的字符循环完了,如果不是模糊的,看在source里匹配的位置是否到达了source的末尾

if (!fuzzy && positionOfSource < sourceLength) {

// System.out.println("上一个字符=" + lastChar +",position=" + position );

return false;

}

return true;// 这里返回true

}

Assert.assertEquals(true, like("abc_d","abc\\_d"));

Assert.assertEquals(true, like("abc%d","abc\\%%d"));

Assert.assertEquals(false, like("abcd","abc\\_d"));

String source ="1abcd";

Assert.assertEquals(true, like(source,"_%d"));

Assert.assertEquals(false, like(source,"%%a"));

Assert.assertEquals(false, like(source,"1"));

Assert.assertEquals(true, like(source,"%d"));

Assert.assertEquals(true, like(source,"%%%%"));

Assert.assertEquals(true, like(source,"1%_"));

Assert.assertEquals(false, like(source,"1%_2"));

Assert.assertEquals(false, like(source,"1abcdef"));

Assert.assertEquals(true, like(source,"1abcd"));

Assert.assertEquals(false, like(source,"1abcde"));

// 下面几个case很有代表性

Assert.assertEquals(true, like(source,"_%_"));

Assert.assertEquals(true, like(source,"_%____"));

Assert.assertEquals(true, like(source,"_____"));// 5个

Assert.assertEquals(false, like(source,"___"));// 3个

Assert.assertEquals(false, like(source,"__%____"));// 6个

Assert.assertEquals(false, like(source,"1"));

Assert.assertEquals(false, like(source,"a_%b"));

Assert.assertEquals(true, like(source,"1%"));

Assert.assertEquals(false, like(source,"d%"));

Assert.assertEquals(true, like(source,"_%"));

Assert.assertEquals(true, like(source,"_abc%"));

Assert.assertEquals(true, like(source,"%d"));

Assert.assertEquals(true, like(source,"%abc%"));

Assert.assertEquals(false, like(source,"ab_%"));

Assert.assertEquals(true, like(source,"1ab__"));

Assert.assertEquals(true, like(source,"1ab__%"));

Assert.assertEquals(false, like(source,"1ab___"));

Assert.assertEquals(true, like(source,"%"));

Assert.assertEquals(false, like(null,"1ab___"));

Assert.assertEquals(false, like(source, null));

Assert.assertEquals(false, like(source,""));

好的,这是一个奇怪的解决方案,但我认为仍然应该提到它。

无需重新创建类似的机制,我们可以利用任何数据库中已有的现有实现!

(仅要求您的应用程序必须有权访问任何数据库)。

每次只运行一个非常简单的查询,根据同类比较的结果返回true或false。 然后执行查询,并直接从数据库中读取答案!

对于Oracle数据库:

SELECT

CASE

WHEN 'StringToSearch' LIKE 'LikeSequence' THEN 'true'

ELSE 'false'

END test

FROM dual

对于MS SQL Server

SELECT

CASE

WHEN 'StringToSearch' LIKE 'LikeSequence' THEN 'true'

ELSE 'false'

END test

您所要做的就是用绑定参数替换" StringToSearch"和" LikeSequence",并设置要检查的值。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mendix发布全球低代码报告,中国软件与低代码发展远超全球

调查显示&#xff1a; 1、86%的受访者表示&#xff0c;企业对于开发人员的需求已经达到了白热化的程度。另外&#xff0c;78%的受访企业表示会依靠非技术人员来缓解IT部门的压力。 2、低代码开发用于标准化数据安全、数据建模和可视化、现有工作流程自动化等应用。 3、受访的IT…

Vineyard 加入 CNCF Sandbox,将继续瞄准云原生大数据分析领域

简介&#xff1a; Vineyard 是一个专为云原生环境下大数据分析场景中端到端工作流提供内存数据共享的分布式引擎&#xff0c;我们很高兴宣布 Vineyard 在 2021 年 4 月 27 日被云原生基金会&#xff08;CNCF&#xff09;TOC 接受为沙箱&#xff08;Sandbox&#xff09;项目。 作…

java 电子编号生成器_业务编号生成器

在我们实际做项目的过程中&#xff0c;时常需要生成一些跟业务相关的一些唯一的业务编号&#xff0c;这些编号又需要一定的规则&#xff0c;一般是每生成一个新的编号是在前一个编号的集成上尾号递增1个单位&#xff0c;下面是我业余时间写的一个编号生成器&#xff0c;直接贴代…

殷浩详解DDD:领域层设计规范

简介&#xff1a; 在一个DDD架构设计中&#xff0c;领域层的设计合理性会直接影响整个架构的代码结构以及应用层、基础设施层的设计。但是领域层设计又是有挑战的任务&#xff0c;特别是在一个业务逻辑相对复杂应用中&#xff0c;每一个业务规则是应该放在Entity、ValueObject …

arcgis怎么用python重新排序_python - 根据排序数据添加新的顺序ID号(ArcGIS) - 堆栈内存溢出...

我需要一行代码&#xff0c;它将根据我为数据规定的顺序发出新的顺序ID。 基本上&#xff0c;在按照我的喜好对数据进行排序后&#xff0c;原始的Object_Id对我来说不再是有意义的顺序。 在我的表中&#xff0c;我创建了一个新字段(短整数)。 在现场计算器的预逻辑脚本框中&…

融资 6 亿元后,端点科技将致力于类SaaS化软件服务

据艾瑞咨询最新发布《2021 中国企业级 SaaS 行业研究报告》显示&#xff0c;在疫情催化下&#xff0c;2020 年 SaaS 市场增速飞快&#xff0c;市场规模达538亿元&#xff0c;同比增长48.7%。 随着数字化转型步伐加快&#xff0c;企业对 SaaS 接受度提升&#xff0c;应用场景从…

稳定性之故障应急处理流程

简介&#xff1a; 尽管可以通过稳定性体系建设&#xff0c;来避免出现生产系统故障。但是仍然无法彻底避免一点风险都不会产生&#xff0c;当稳定性风险产生后&#xff0c;怎么快速协调组织&#xff0c;缩短故障时长&#xff0c;科学的流程呢&#xff1f; 作者 | 金喜 来源 | 阿…

java 参数传值的练习题及答案_java方法参数传递面试题三则

传值还是传引用是Java中很基础的一个问题&#xff0c;也是笔试的时候经常被考察的一个问题&#xff0c;总结一下。题目1&#xff1a; 写出以下程序的输出内容。public class Test {public static void changeValue(int value){value 0;}public static void main(String[] args…

如何限制浏览器使用_论如何优雅地使用chrome 浏览器

chrome 浏览器目前已经算得上是在浏览器市场独占鳌头了&#xff0c;就连它的最强对手IE也不得不低下头颅改用Chromium内核&#xff0c;这让chrome 浏览器更是没有对手了&#xff0c;但是你真的了解这个你时时刻刻都在用到的浏览器吗&#xff1f;今天装糊涂先森就来教你如何优雅…

520,一份给程序员的“硬核”脱单秘籍

简介&#xff1a; 各位&#xff0c;520快乐&#xff01; 今天是个粉红色的日子&#xff0c;我们来聊聊和技术无关的“技术活”&#xff0c;比如&#xff1a;“如何表白&#xff1f;”当技术人碰上心动的姑娘&#xff0c;他的浪漫开关就打开了。 各位&#xff0c;520快乐&#…

95后架构师晒出工资单:狠补了这个,真香...

前段时间看见某95后阿里P7晒出工资单&#xff0c;我是真酸了……只能狠补一下技术了。Java 一面基本上都是基础题&#xff0c;同样是 CURD 的活&#xff0c;谁更熟练要谁&#xff0c;比如下面这个Java面试手册&#xff0c;八股文越熟练越容易通过 Java 面试。这份资料内容涵盖极…

阿里云 EDAS 3.0 助力唱鸭提升微服务幸福感

简介&#xff1a; EDAS 3.0 提供的微服务治理&#xff0c;很好的支持了唱鸭 APP 实现微服务应用的发布、监控、管理等日常业务场景。作为运维侧的重要平台和开框架的提供者&#xff0c;EDAS 3.0 帮助用户可以更专注业务。微服务架构升级后&#xff0c;业务具备水平扩展能力&…

java 生产者消费者 demo_生产者与消费者--demo1---bai

import java.util.ArrayList;import java.util.List;import java.util.Random;//自定义类&#xff0c;描述仓库public class StoreHouse{private List products new ArrayList(); //仓库的所有商品的列表public void add(String product){this.products.add(product);}Random …

python字典是什么数据结构_Python常用数据结构——字典

Time will tell.前言迄今为止&#xff0c;我们已经为大家介绍了Python中的三种容器型数据类型&#xff0c;但是这些数据类型还不足以帮助我们解决所有的问题。例如&#xff0c;我们要保存一个人的信息&#xff0c;包括姓名、年龄、体重、单位地址、家庭住址、本人手机号、紧急联…

Serverless:这真的是未来吗?(二)

简介&#xff1a; 在关于无服务器的第二篇文章中&#xff0c;我们将讨论一些更广泛的问题。再次强调&#xff0c;我们并不是要做硬性规定。我们想提出一些观点&#xff0c;以促进所有利益相关者之间的讨论。许多说所有应用程序都将是无服务器的应用程序的人并未大规模运行其应用…

删除超过10亿用户的数据,Facebook 关闭面部识别系统

整理 | 祝涛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;Facebook周二宣布&#xff0c;计划在本月关闭其已有10年历史的面部识别系统&#xff0c;并删除超过10亿用户的面部扫描数据&#xff0c;原因是这项技术的使用引发了越来越多的社会担忧。Facebook新…

参与 Apache 顶级开源项目的 N 种方式,Apache Dubbo Samples SIG 成立!

简介&#xff1a; 一说到参与开源项目贡献&#xff0c;一般大家的反应都是代码级别的贡献&#xff0c;总觉得我的代码被社区合并了&#xff0c;我才算一个贡献者&#xff0c;这是一个常见的错误认知。其实&#xff0c;在一个开源社区中有非常多的角色是 non-code contributor&a…

python中bar的用法_python使用matplotlib绘图 -- barChart

matplotlib 是python最著名的绘图库&#xff0c;它提供了一整套和matlab相似的命令API&#xff0c;十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件&#xff0c;嵌入GUI应用程序中。它的文档相当完备&#xff0c;并且Gallery页面 中有上百幅缩略图&#xff0c;打开…

java在cmd中什么意思_为什么在cmd中java可以运行,javac不行?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼Path: C:\Program Files\NVIDIA Corporation\PhysX\Common;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jdk1.8.0_05\bin;C:\Program F…

重磅 | 《中国移动云网一体产品白皮书(2021)》发布!

11月1日—11月3日&#xff0c;2021中国移动全球合作伙伴大会在广州隆重召开。11月2日&#xff0c;中国移动云能力中心副总经理孙少陵发表了《移动云技术内核2.0》主旨演讲&#xff0c;并在会上发布了《中国移动云网一体产品白皮书&#xff08;2021&#xff09;》。云网一体是市…