Java 9中的新Regex功能

最近,我收到了Packt出版的Anubhava Srivastava提供的免费书籍“ Java 9 Regular Expressions” 。 这本书是一个很好的教程,它向任何想学习正则表达式并从头开始的人介绍。 那些知道如何使用正则表达式的人可能仍然很有趣,以重申其知识并加深诸如零长度断言,反向引用之类的复杂特征。

在本文中,我将重点介绍特定于Java 9且在早期版本的JDK中不可用的正则表达式功能。 虽然没有很多。

Java 9正则表达式模块

Java 9中的JDK分为多个模块。 可以理所当然地期望为正则表达式处理包和类提供一个新模块。 其实没有。 模块java.base是默认模块,默认情况下所有其他模块都依赖该模块,因此,导出的包的类在Java应用程序中始终可用。 此模块导出正则表达式包java.util.regex 。 这使开发过程更加简单:如果我们想在代码中使用正则表达式,则无需显式地“要求”模块。 似乎正则表达式对于Java是如此重要,以至于它包含在基本模块中。

正则表达式类

java.util.regex包含这些类

  • MatchResult
  • Matcher
  • Pattern
  • PatternSyntaxException

更改API的唯一类是Matcher

类匹配器的变化

Matcher类添加了五个新方法。 其中四个是现有方法的重载版本。 这些是:

  • appendReplacement
  • appendTail​
  • replaceAll​
  • replaceFirst​
  • results​

前四个存在于较早的版本中,并且参数的类型仅发生变化(毕竟这就是重载的意思)。

appendReplacement / Tail

对于appendReplacementappendTail ,唯一的区别是该参数还可以是StringBuilder ,而不仅仅是StringBuffer 。 考虑到StringBuilder是Java 1.5中引入的,就像13年前一样,没有人可以说这是一个不明智的行为。

有趣的是,API JDK的当前在线版本如何记录StringBuilder参数的appendReplacement行为。 较旧的StringBuffer变量方法显式记录了替换字符串可能包含将由相应组替换的命名引用。 StringBuilder论据版本错过了这一点。 该文档似乎像复制/粘贴然后进行编辑。 文本将“ buffer”替换为“ builder”等,并删除记录命名参考功能的文本。

我使用Java 9 build160尝试了该功能,对于这两个方法版本,结果是相同的。 这并不奇怪,因为这两种方法的源代码是相同的,除了参数类型之外,在JDK中都是简单的复制/粘贴。

似乎可以使用

@Testpublic void testAppendReplacement() {Pattern p = Pattern.compile("cat(?<plural>z?s?)");//Pattern p = Pattern.compile("cat(z?s?)");Matcher m = p.matcher("one catz two cats in the yard");StringBuilder sb = new StringBuilder();while (m.find()) {m.appendReplacement(sb, "dog${plural}");//m.appendReplacement(sb, "dog$001");}m.appendTail(sb);String result = sb.toString();assertEquals("one dogz two dogs in the yard", result);}

注释行或每行上方的行。 但是,文档仅涉及编号参考。

replaceAll / First

这也是一种“旧的”方法,用一些新的字符串替换匹配的组。 旧版本和新版本之间的唯一区别是替换字符串的提供方式。 在老版本的字符串被赋予作为String调用方法之前计算。 在新版本中,字符串作为Function<MatchResult,String> 。 将为每个匹配结果调用此函数,并且可以动态计算替换字符串。

知道Function类是3年前才在Java 8中引入的,因此在正则表达式中对它的新使用可能有点破绽。 或者,也许……也许我们应该将其视为一个提示,即从现在开始十年,当Fuction类已经13岁时,我们仍将拥有Java 9?

让我们更深入地研究这两种方法。 (实际上只用于replaceAll因为replaceFirst相同,只不过它只替换第一个匹配的组。)当这种用法很有价值时,我尝试创建一些并非绝对复杂的示例。

第一个示例来自JDK文档:

@Testpublic void demoReplaceAllFunction() {Pattern pattern = Pattern.compile("dog");Matcher matcher = pattern.matcher("zzzdogzzzdogzzz");String result = matcher.replaceAll(mr -> mr.group().toUpperCase());assertEquals("zzzDOGzzzDOGzzz", result);}

它不太复杂,并显示了功能。 使用lambda表达式绝对足够。 我无法想象一种简单的方法将常量字符串文字“ dog”大写。 也许只写“ DOG”。 好吧,我只是在开玩笑。 但是实际上这个例子太简单了。 对于文档来说是可以的,更复杂的事情会使读者分心于所记录方法的功能。 确实:不要期望JavaDoc中的复杂示例更少。 它描述了如何使用API​​,而不是描述了为何以这种方式创建API。

但是现在我们现在将看一些更复杂的例子。 我们要在字符串中用数字1、2、3等替换#字符。 该字符串包含编号的项目,如果我们在该字符串中插入一个新项目,我们不想手动重新编号。 有时我们将两个项目组合在一起,在这种情况下,我们编写## ,然后只想跳过下一个#的序列号。 由于我们已经进行了单元测试,因此代码比我可以用语言更好地描述了功能:

@Testpublic void countSampleReplaceAllFunction() {AtomicInteger counter = new AtomicInteger(0);Pattern pattern = Pattern.compile("#+");Matcher matcher = pattern.matcher("# first item\n" +"# second item\n" +"## third and fourth\n" +"## item 5 and 6\n" +"# item 7");String result = matcher.replaceAll(mr -> "" + counter.addAndGet(mr.group().length()));assertEquals("1 first item\n" +"2 second item\n" +"4 third and fourth\n" +"6 item 5 and 6\n" +"7 item 7", result);}

传递给replaceAll的lambda表达式获取计数器并计算下一个值。 如果我们使用一个#那么如果我们使用两个,它将增加1,然后将其添加到计数器,依此类推。 因为lambda表达式不能在周围环境中更改变量的值(变量必须有效地为final),所以计数器不能为intInteger变量。 我们需要一个具有int值并且可以更改的对象。 即使我们不使用AtomicInteger的原子功能,它也是如此。

下一个示例更进一步,并进行了一些数学计算。 它将字符串中的任何浮点格式的数字替换为其正弦值。 这样,由于sin(pi)甚至与pi都不接近,因此它可以纠正我们的句子,此处无法精确表示。 它几乎接近零:

@Testpublic void calculateSampleReplaceAllFunction() {Pattern pattern = Pattern.compile("\\d+(?:\\.\\d+)?(?:[Ee][+-]?\\d{1,2})?");Matcher matcher = pattern.matcher("The sin(pi) is 3.1415926");String result = matcher.replaceAll(mr -> "" + (Math.sin(Double.parseDouble(mr.group()))));assertEquals("The sin(pi) is 5.3589793170057245E-8", result);}

我们还将对此计算进行一些操作,以演示列表中的最后一个方法,它是Matcher类中的一个全新方法。

流结果()

新方法results()返回匹配结果流。 更精确地说,它返回MatchResult对象的Stream 。 在下面的示例中,我们使用它从字符串中收集任何浮点格式的数字,并以逗号分隔打印其正弦值:

@Testpublic void resultsTest() {Pattern pattern = Pattern.compile("\\d+(?:\\.\\d+)?(?:[Ee][+-]?\\d{1,2})?");Matcher matcher = pattern.matcher("Pi is around 3.1415926 and not 3.2 even in Indiana");String result = String.join(",",matcher.results().map(mr -> "" + (Math.sin(Double.parseDouble(mr.group())))).collect(Collectors.toList()));assertEquals("5.3589793170057245E-8,-0.058374143427580086", result);}

摘要

Java 9 JDK中引入的新正则表达式方法与现有的方法没有本质上的区别。 它们整洁方便,在某些情况下可以简化编程。 在早期版本中没有没有引入的任何内容。 这只是Java缓慢而深思熟虑地对JDK进行此类更改的方式。 毕竟,这就是我们爱Java的原因,不是吗?

可以从以下要点中找到并下载IDE中的整个代码副本粘贴

翻译自: https://www.javacodegeeks.com/2017/08/new-regex-features-java-9.html

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

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

相关文章

c语言实现二分法_C语言实现二分法求解方程在区间内的根

C语言实现二分法求解方程在区间内的根。设有非线性方程&#xff1a;其中&#xff0c; 为 上连续函数且设 (不妨设方程在 内仅有一个实根)&#xff0c;求上述方程实根的二分法过程&#xff0c;就是将含根区间[a,b]逐步分半&#xff0c;检查函数值符号的变化&#xff0c;以便确定…

计划

赤 wqs二分 https://www.cnblogs.com/Juve/p/11479423.html https://www.cnblogs.com/Rorschach-XR/p/11479602.html 反悔贪心 https://www.cnblogs.com/cjyyb/p/9367948.html https://www.cnblogs.com/Miracevin/p/9795871.html https://blog.csdn.net/weixin_34344677/articl…

java写入文件编码格式为ansi_Windows10 bat批处理删除 快速打开文件夹 固定到开始菜单或任务栏...

1. 快速打开文件夹1.1 bat文件如果你经常打开一个被放在很深的文件夹&#xff0c;于是浪费很多打开文件的时间&#xff1a;开始>此电脑>Data(D:)>文件夹1>文件夹2...>文件夹n>平均要浪费大约10秒的时间&#xff0c;如果每天打开100次&#xff0c;那么1000秒&…

python中__init__.py的作用、module和package

控制包的导入行为&#xff1a; 1、声明当前文件是一个可导入的包&#xff1b;2、如果当下包下有多个.py文件使用__ all__ [ 模块名]&#xff0c;也就是form XXX import YYYmodule和package 为了编写可维护的代码&#xff0c;我们把很多函数分组&#xff0c;分别放到不同的文件…

java default修饰符_Java基础语法二

Java循环结构for循环/* for(初始化;布尔表达式;更新) {执行代码 } */ for(int i0; i < 5; i) {System.out.println(i); }最先执行初始化步骤&#xff1b;可以声明一种类型&#xff0c;但可初始化一个或多个循环控制变量&#xff0c;也可以是空语句然后检测布尔表达式&#x…

微信开发修改button里的字体大小_微信小程序全栈开发课程【视频版】2.2 index页面完善...

​点击观看视频课程 ↓↓↓微信小程序首页完善https://www.zhihu.com/video/1195308096099282944课程文字版1、template 部分&#xff08;1&#xff09;修改template部分的代码template里面包含html代码&#xff0c;对应着原生小程序框架里中的.wxml文件。我们将index.vue文件中…

jaxb list集合对象_JAXB –表示空集合和空集合

jaxb list集合对象示范代码 以下演示代码将用于Java模型的所有不同版本。 它只是将一个集合设置为null&#xff0c;第二个设置为空列表&#xff0c;第三个设置为填充列表。 package package blog.xmlelementwrapper;import java.util.ArrayList; import javax.xml.bind.*;publ…

.net 把一个对象赋值给一个参数_Java GC回收算法-判定一个对象是否可以回收

开源推荐推荐一款一站式性能监控工具&#xff08;开源项目&#xff09;Pepper-Metrics是跟一位同事一起开发的开源组件&#xff0c;主要功能是通过比较轻量的方式与常用开源组件&#xff08;jedis/mybatis/motan/dubbo/servlet&#xff09;集成&#xff0c;收集并计算metrics&a…

管理角色认知-新晋管理常常犯的错

背景 管理是一门实践科学&#xff0c;从知道到做到&#xff0c;需要长时间的刻意练习&#xff0c;提前知道那些坑&#xff0c;可以提前规避。 坑1&#xff1a;被动执行 现象&#xff1a; 不主动找活干&#xff0c;等上级派活&#xff1b; 上级有了安排&#xff0c;指望上级替他…

头条号个人中心登录_登陆自己的头条号后台操作步骤

作为一个自媒体新人对自媒体的知识还是不够了解的&#xff0c;有的新人甚至还不知道什么是头条号后台&#xff0c;这篇文章是专为新手写的一篇文章&#xff0c;带你走进你的头条号后台遛一圈。那么什么是头条号后台呢&#xff1f;这里笔者就作下简单的介绍方便新人学习。登陆自…

python保存变量_将python 中的变量保存到本地

如何将python中的变量保存在本地&#xff1f; 将python 的一些代码保存在本地&#xff0c; 特别是一些需要大量运算的结果&#xff0c;例如 机器学习里面的模型&#xff0c;&#xff0c;放在本地&#xff0c;还是比较好用的。下次就可以直接拿出来使用就好。 其实可以 我觉得可…

django filter查询多选_Django:使用filter的pk进行多值查询操作

由于想要做收藏夹的功能&#xff0c;所以希望能够一次性查询出所有id的对象&#xff0c;查看文档&#xff0c;找到了如下方法pk是primary key的缩写&#xff0c;顾名思义pk_in就是primary key在某一个范围内&#xff0c;具体操作(以自带的User为例)&#xff1a;User.objects.fi…

csp-c模拟测试「set·read·」

set 题解 只要求一组特解 像入阵曲一样就好了(入阵曲真是好题啊$!$) $(sum[r]-sum[l])\%n0$ 拆成$sum[r]\%nsum[l]\%n$桶里存$sum[l]\%n$每次找$sum[r]$桶里有没有对应的#sum[l]# 存$tong[0]1$,别的先查后存 证明 证明一下正确性 $0$自己合法$(sum[r]\%n)0$不需要找对应 其他都…

JSP,JSF和EL简介

JavaServer页面&#xff0c;JavaServer Faces和表达语言 在本文中&#xff0c;我将研究JavaServer Pages&#xff08;JSP&#xff09;和Expression Language&#xff08;EL&#xff09;&#xff0c;然后将其与JavaServer Faces &#xff08;JSF&#xff09;关联。 我将讨论如何…

stream模式不能接受blob文件_一文带你层层解锁文件下载的奥秘

今天带来的主题是关于文件下载&#xff0c;通过本文带你领略文件下载的奥秘。本文会花费你较长的时间阅读&#xff0c;建议先收藏/点赞&#xff0c;然后查看你感兴趣的部分&#xff0c;平时也可以充当当做字典的效果来查询。:) 不整不知道&#xff0c;一整&#xff0c;居然整出…

# 管道已结束_县城这条路启用自来水新管道,看看是否在你家附近...

连日来&#xff0c;县自来水公司的工作人员顶着高温抓紧作业&#xff0c;目前&#xff0c;县城范堤路自来水管道改造工程已过半&#xff0c;预计本月中旬完工。施工现场1目前&#xff0c;盐垣路至掘中路的新管道正在进行对接&#xff0c;为了确保启用新管道后的用水安全&#x…

python 中的eval与exec

eval类似exec,是使用python编译器运行表达式和语句两者区别在于:eval是编译表达式并返回值(如: eval("hello*2") 结果是 hellohello)exec则是运行一部分代码,并且不像eval那样返回结果,exec的返回值永远是None,且exec可运行多行代码(如: exec("l[1,2,3]\nfor i …

启动时指定需要绑定的网卡_为什么小型汽油机在启动时需要拉风门,而汽车却不用?...

很多人都有骑小型摩托车的经验&#xff0c;在启动摩托车时&#xff0c;一般要把“合风”拉上&#xff0c;否则摩托车启动就会很困难。特别是在天气比较寒冷时&#xff0c;如果不拉上合风&#xff0c;摩托车很难启动。但是在汽车上却没有“合风”这个装置&#xff0c;我们在启动…

java 栈和队列实现迷宫代码_Python 实现数据结构中的的栈,队列

栈栈(stack)又名堆栈&#xff0c;它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶&#xff0c;相对地&#xff0c;把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈&#xff0c;它是把新元素放到栈顶元素的上面&#xff…

管理任务执行-如何排任务优先级

背景 工程师出生的管理者擅长做任务管理&#xff0c;凡是明确答应过的事情&#xff0c;一般会如数兑现。 研究的含义 研究模块核心管理规划把事情做对团队建设理顺做事的主体任务管理把事情做出来&#xff0c;产出实实在在的业绩和成果做事【任务管理】是非常重要的管理内容 对…