范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Java性能调优代码篇优化正则表达式的匹配效率

  作者 | 浩说编程
  来源 | 公众号:浩说编程
  [ 大厂技术资源 | 研发必备安装包 | 限时免费获取 ]
  在我们的日常业务开发中经常会涉及到使用正则表达式对数据进行处理,比如String的Split()方法,它根据方法中传入的正则表达式对字符串做分割处理。
  但是我们是否真的了解正则表达式,它是如何匹配的?不同的匹配方式会带来怎样的效率差别?怎样才能做到效率最优?
  本篇就对"如何优化正则表达式的匹配效率?"做深入探讨。
  一、匹配的三种方式
  看下面这个例子,我们给定了一个字符串以及三个功能相同但写法略有区别的正则表达式:String testStr = "effg"; String regular_1 = "ef{1,3}g"; String regular_2 = "ef{1,3}?g"; String regular_3 = "ef{1,3}+g"; 1234
  用split方法测试每个正则表达式运行的时间:List regulars = new ArrayList<>(); regulars.add(regular_1); regulars.add(regular_2); regulars.add(regular_3);  for(String regular : regulars){     long start,end;     start = System.currentTimeMillis();     testStr.split(regular);     end = System.currentTimeMillis();     System.out.println((end - start) + "(ms)"); } 123456789101112
  控制台输出(为了体现效率差别,测试的时候我将上面的字符串复制成了足够的长度):2(ms) 1(ms) 0(ms) 123
  可以明显看到,虽然实现了相同的匹配功能,但效率却有所区别,原因在于这三种写法定义了正则表达式的三种匹配逻辑,我们来逐一说明:
  码文不易
  你的关注是浩说编程持续更新的动力
  浩说编程会做的更好
  1、贪婪模式(Greedy): ef{1,3}g
  贪婪模式是正则表达式的默认匹配方式,在该模式下,对于涉及数量的表达式,正则表达式会尽量匹配更多的内容,我用模型图来演示一下匹配逻辑
  到第二步的时候其实已经满足第二个条件f{1,3},但我们说过贪婪模式会尽量匹配更多的内容,所以依然停在第二个条件继续遍历字符串
  注意看第四步,字符g不满足匹配条件f{1,3},这个时候会触发回溯机制:指针重新回到第三个字符f处
  关于回溯机制
  回溯是造成正则表达式效率问题的根本原因,每次匹配失败,都需要将之前比对过的数据复位且指针调回到数据的上一位置,想要优化正则表达式的匹配效率,减少回溯是关键。
  回溯之后,继续从下一个条件以及下一个字符继续匹配,直到结束
  2、懒惰模式(Reluctant): ef{1,3}?g
  与贪婪模式相反,懒惰模式则会尽量匹配更少的内容:
  到第二步的时候,懒惰模式会认为已经满足条件f{1,3},所以会直接判断下一条件
  注意,到这步因为不满足匹配条件,所以触发回溯机制,将判断条件回调到上一个
  回溯之后,继续从下一个条件以及下一个字符继续匹配,直到结束
  3、独占模式(Possessive): ef{1,3}+g
  独占模式应该算是贪婪模式的一种变种,它同样会尽量匹配更多的内容,区别在于在匹配失败的情况下不会触发回溯机制,而是继续向后判断,所以该模式效率最佳
  在了解了三种匹配方式的匹配逻辑之后,给出第一个优化建议优化建议一:
  推荐在使用正则表达式的时候,采用独占模式效率最佳,因为触发回溯的概率最小。
  二、优化正则中的分支选择
  通过上面对正则表达式匹配逻辑的了解,我们不难想到,由于回溯机制的存在,带有分支选择的正则表达式必然会降低匹配效率String testStr = "abbdfg"; String regular = "(aab|aba|abb)dfg"; 12
  在这个例子中,"aab"并未匹配,于是回溯到字符串的第一个元素重新匹配第二个分支"aba",以此类推,直到判断完所有分支,效率问题可想而知。
  那么应该如何优化呢?这里给出特定情况下的两种优化建议:优化建议二:
  首先,如果分支中存在公共前缀可以提取公共部分String regular = "a(ab|ba|bb)dfg"; 1
  这样首先减少了公共前缀的判断次数,其次降低了分支造成的回溯频率,相比之下效率有所提升。优化建议三:
  第二种方式是,如果分支中的元素比较简单,可以使用indexOf方法匹配testStr.indexOf("aab"); testStr.indexOf("aba"); testStr.indexOf("abb"); 123
  虽然这两个建议能够优化匹配效率,但只是相比之下的优化,分支选择的机制就决定了势必要进行多次的回溯判断,所以分支选择建议能不用就不用。
  三、优化正则中的捕获组
  捕获组在正则表达式中通常用"()"表示,它将其中匹配到的内容保存到一个数组中,以便之后使用。
  例如我们想获取前端input中的内容:String inputStr = "userName"; 1
  定义带有捕获组的正则表达式,并输出捕获组存入数组中的内容String regular = "()(.*?)()"; Pattern pattern = Pattern.compile(regular); Matcher matcher = pattern.matcher(inputStr); while(matcher.find()){   System.out.println(matcher.group(0));   System.out.println(matcher.group(1));   System.out.println(matcher.group(2));   System.out.println(matcher.group(3)); } 123456789
  控制台输出:userName  userName  1234
  看到这里大家应该理解了捕获组的用法,第三行就是我们需要的内容,但需要优化的是,第二行以及第四行的内容我们并不需要,这会影响效率以及内存损耗。
  对于这种情况我们可以使用"(? : )"来代替"()",区别在于前者不会将匹配的内容存入数组:String regular = "(?:)(.*?)(?:)"; Pattern pattern = Pattern.compile(regular); Matcher matcher = pattern.matcher(inputStr); while(matcher.find()){   System.out.println(matcher.group(0));   System.out.println(matcher.group(1)); } 1234567
  控制台输出:userName userName 12优化建议四:
  对于存在捕获组的正则表达式,如果信息不需要保存,则使用"(?: )"来替代"()"
  总结
  本篇针对正则表达式的三个点:匹配模式、选择分支、捕获组,分析出了三个优化建议:
  1、推荐在使用正则表达式的时候,采用懒惰模式和独占模式效率最佳,因为触发回溯的概率最小。
  2、分支选择建议尽量避免使用,特定条件下可以采用提取公共前缀、indexOf方法优化
  3、对于存在捕获组的正则表达式,如果信息不需要保存,则使用"(?"来替代"()"
  以上就是本篇的内容,希望对读者有所帮助,浩说编程帮你学到更多。
  作者 | 浩说编程
  来源 | 公众号:浩说编程

随身wifi怎么用?随身wifi怎么用随身wifi就是可以随身携带的wifi信号,通过无线移动路由器和无线运营商提供的无线上网芯片(sim卡),组成一个可以移动的wifi接收发射信号源。随身wifi怎所有人CIT2021中国全宅影音集成展观展指南来了向各位发送一份CIT2021中国全宅影音集成展观展指南。在即将到来的7月5日,2021中国全宅影音集成展将于北京国家会议中心拉开序幕,成为七一后首个于北京举办的大型影音智能综合展会月付24。99美元,美亚推出月付费制黑胶俱乐部黑胶迷的春天来了。美国亚马逊推出AmazonVinyloftheMonthClub(亚马逊月度最佳黑胶俱乐部)活动,即每月支付24。99美元(约合162元),就能获得一张黑胶唱片。CIT2021参展商巡礼浙江澳森实业有限公司作为国内集家用与专业影音集成两者于一体的综合性大型展会,从2011年开始,CIT中国影音集成科技展已经成为影音集成行业的交流殿堂,拥有覆盖面广与行业性强的突出优势,面向范围囊括全宅宁波钱湖四季苑案例赏析优秀的全宅智能ampampamp影音集成,是看不见的基本情况简介实施方类别影音设计师案例类别定制影院室内户外背景音乐系统位置及周边概括性描述宁波钱湖四季苑资金投入总投入约200万元(包括智能系统和影音系统)空间信息建筑面积大概在22Optoma(奥图码)EL500K难得的透明感与立体感,0。66英寸UHD4K芯片与高亮度激光的结合在炎热的6月,我们迎来了这两年难得一见的包括家庭影院投影机与激光电视在内的,家用大屏解决方案的新品爆发期。其中在家庭影院投影机方面,今年所涌现的新作在技术上强调的方向主要有两个方面随身WiFi别小看了它的用途,真香警告最近听到一个熟悉而又陌生的词随身WiFi。对于这个东西,应该有很多朋友都很陌生。因为随着科技的发展,网络遍布世界各个地方,大家基本上都不会出现没网的烦恼。自然而然,对于随身WiFiEsotericK1X藏在美之后的工艺和科学若要说目前世界上SACD机中最为受人们尊敬的品牌,那莫过于日本Esoteric,多年以来,Esoteric始终以专利和科技跑在SACD机发展的最前线。自Esoteric推出SACD入墙吸顶APP调校细数低音炮的隐身妙招在客厅影院或家庭影院系统中,低音炮一向被认为是最难隐藏的。通常情况下,它都以四四方方的箱体外摆在空间中,令人无法忽视。但你是否想过,低音炮也可以横躺着塞进沙发底下,入墙甚至吸顶安装对性能的追求只会提高,不会降低,NADM28多声道功率放大器NAD与Hypex公司之间的合作很深,在很长的一段时间里,NAD的功放全系列都使用Hypex的D类功放模块。2014年,Hypex的灵魂人物BrunoPutzeys与PeterLy科普AppleMusic无损音乐专题(完)前文回顾Qobuz始终坚持真高解析度无损音乐Qobuz也是另一个发烧友爱用的在线流媒体音乐平台,于2007年在法国创立。Qubuz在无损音乐方面最高能提供24bit192kHz规格
TANCHJIMDarling三单元圈铁,一种别样的张狂有些老爷车,是真的漂亮,那是一种张狂与精致并存的美感,每个细节都透着属于特定时代的自信与激昂。就包括Mini这种身上带有充分经典印记的现代作品,走在街上的回头率也是明显偏高的,所以199元的塞子做到这个样子还要啥自行车?锐可余音SG01锐可余音这条SG01,包装看起来少说像是三五百块的产品拆开之后一看这金属腔体可换线插头以及绝不拉胯的做工和配件,判断它具备千元塞的设定和卖相听了一耳朵发现素质还不错,500左右的水HIDIZSS3Pro这么个可爱又优秀的小家伙,卖你439软妹币,不算贵吧这篇文章的开头,是老生常谈1iPhone4面世之后,到iPhone7诞生之前的那几年,是音频行业最幸福的岁月,彼时所有手机都有3。5耳机口,而且Beats为代表的品牌让消费者意识到途昂新对手,标配3。5L发动机,31万起售,纯进口品质为你和家人,做坚实的守护者。9月10日,现代进口汽车帕里斯帝(PALISADE)举办线上发布会,以一场视听盛宴解密帕里斯帝(PALISADE),开启大型SUV聚焦家庭出行的新时代。乞版车型卖到32万,广汽丰田赛那还妄想插翅飞?在广汽丰田公布赛那SIENNA预售价之后,相信刚刚遭遇了一波疯狂吐槽的第四代嘉华总算是松了一口气,毕竟赛那3242万元的预售价格直接将自己送上了风口浪尖且不说未来终端是否真的能够买上汽大通MAXUSD90Pro2021款500Nm动力,透明底盘,不到20万?心之所至,探索四方。7月15日,专业级SUV标杆上汽大通MAXUSD90Pro2021款智勇登场。基于C2B智能定制模式,D90Pro2021款可为越野爱好者实现私人定制,蜘蛛定制专业音响空间的组建标准有哪些声拓电子音爵士专业音响空间的组建标准有哪些声拓电子音爵士专业音响设备和普通音响设备的不同之处就在于它的专业性,因为在不同的空间人们发出的声音都是不一样的,音响也是一样的在不同的空间,音响都有自己盖世小鸡X2游戏手柄,玩PSPSP无所不能,连NS都拿下游戏手柄这个产品相信大家都不会陌生,无论是主机游戏PC游戏或是掌机游戏,都离不开手柄。有手柄的支持,玩起游戏也会更加的爽快。而来到智能手机风靡的年代,手游铺天盖地,手游手柄更是火了2021宏碁全球秋季发布会推出抗菌家族,共筑健康屏障2021年10月13日晚9点以因你而生未你而来为主题的宏碁2021全球秋季新品发布会召开,在当前全新的生活方式也唤起了用户对于个人健康的注意,宏碁持续关注并回应用户面对生活挑战的转提升时尚品味就这么简单,韩国大宇手持挂烫机,开启精致小资生活相信很多女生购买衣服,都有这样的经历在店里,试穿挂版的衣服,美美的,品味气质十足。高高兴兴的,营业员从仓库中取出全新的衣服,拿回家中,穿上去,却总感觉哪里不对。在网上买衣服,上身效助力西部安全产业发展,腾讯携手西安院校发布云安全优才计划助力西部安全产业发展,腾讯携手西安院校发布云安全优才计划9月26日,由腾讯安全腾讯安全云鼎实验室陕西省计算机学会联合主办的2021首届西部云安全峰会在西安顺利召开。本次峰会以聚焦云