第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

String.replaceAll方法,正則妙用

標(biāo)簽:
Java

小姐姐味道【ID:xjjdog】
作者:十年架构,日百亿流量经验,与你分享。

https://img1.sycdn.imooc.com//5d382d6a0001473b03650174.jpg

我通常是不太关心代码的具体实现的,因为我的开发语言很杂,倾向于一些最简单通用的方式去解决。今儿不小心在群里看到一位朋友发了下面的java代码,感觉自己还是很局限很无知的:

String str1 = "createTime";
String str2 = "createTimeAt";
String regex = "([A-Z])+";

System.out.println(str1.replaceAll(regex, "_$1").toLowerCase());
System.out.println(str2.replaceAll(regex, "_$1").toLowerCase());

//result
//create_time
//create_time_at

通过输出可以看到,这段代码的作用是把驼峰命名格式的字符串替换成下划线分割,这个功能比较简单,但是吸引我的却是他的代码。

"createTime".replaceAll("([A-Z]+)","_$1")

这行代码简单的很,就是调用了String类的replaceAll方法,方法的第一个参数是正则表达式,第二个参数是将要被替换成的新值。

让我惊奇的是他代码中,replaceAll的第二个参数,也就是JDK文档中名为replacement的参数,竟然是_$1。这是什么鬼?还支持类似占位符这样的东西?我一直都不知道。

问题探索

由于之前研究过一段正则表达式,通过观察replaceAll的第一个参数([A-Z]+),我猜想,这个应该是用到了正则表达式的分组,对应JDK中,就是java.util.regex.Matcher类的group()方法。

在Linux的Sed命令上,就使用&进行了一些替换,道理应该是相通的。

于是看了下String.replaceAll方法是如何实现的。JDK:

public String replaceAll(String regex, String replacement) {
       return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}

哦,原来它底层就是用了Matcher,只不过用的是Matcher自己的replaceAll方法。
去看它的文档,这个方法的参数果然有鬼,看下面实现代码。

public String replaceAll(String replacement) {
       reset();
       boolean result = find();
       if (result) {
           StringBuilder sb = new StringBuilder();
           do {
               appendReplacement(sb, replacement);
               result = find();
           } while (result);
           appendTail(sb);
           return sb.toString();
       }
       return text.toString();
   }

里面关键的部分就是文档中说的appendReplacement方法,然后可以看到详细的描述文档。

看到这里明白了,原来这个方法的replacement参数可以通过$字符来指代Matcher通过正则匹配得到的分组,支持name和number 两种方式,这里对应的就是Matcher类的group(name)和group(int)两个方法。

结论

1、String的replaceAll方法实际上是通过java.util.regex.Matcher类的replaceAll()方法实现的。
2、java.util.regex.Matcher类的replaceAll方法又是通过调用appendReplacement方法实现替换逻辑
3、Matcher类的appendReplacement方法的replacement参数支持通过$符号来指代Matcher匹配的分组

下面这串代码,就是使用Matcher类分组的一个最佳实践。

String data = "哈哈哈,xjjdog的手机号码是:12345678901,你会打给我吗";
//通过Matcher的分组功能,可以提取出上面字符串中的手机号
Matcher matcher = Pattern.compile(".*(xjjdog的手机号码是:([0-9]{11}))").matcher(data);
while (matcher.find()) {
   System.out.println("G0:" + matcher.group(0));
   System.out.println("G1:" + matcher.group(1));
   System.out.println("G2:" + matcher.group(2));
}
//result
//G0:哈哈哈,xjjdog的手机号码是:12345678901
//G1:xjjdog的手机号码是:12345678901
//G2:12345678901

group(0)表示整个字符串
group(1)表示第一个匹配的,上面的例子中就是(我的手机号码是:([0-9]{11}))部分
group(2)表示第二个匹配的,上面的例子中就是([0-9]{11})部分

使用分组可以用来提取字符串中的目标字符串值,很好用!

几个例子

下面是几个例子,大家可以触类旁通。

驼峰转下划线命名

public static String camelToUnderline(String camelName) {
return camelName.replaceAll("([A-Z]+)", "_$1").toLowerCase();
}

下划线转驼峰

这个稍微麻烦点,是模仿者Matcher.replaceAll方法写的。

public static String underlineToCamel(String underlineName) {
       Matcher matcher = Pattern.compile("(_[a-z]{1})").matcher(underlineName);
       StringBuffer result = new StringBuffer();
       while (matcher.find()) {
           String replacement = matcher.group(1);
           matcher.appendReplacement(result, replacement.replace("_", "").toUpperCase());
       }
       matcher.appendTail(result);
       return result.toString();
}

另外,Mybatis Generator插件源码中的也提供了类似方法(JavaBeansUtil.getCamelCaseString),这里做了下简单修改

 public static String getCamelCaseString(String inputString) {
       StringBuilder sb = new StringBuilder();
       boolean nextUpperCase = false;
       for (int i = 0; i < inputString.length(); i++) {
           char c = inputString.charAt(i);
           switch (c) {
               case '_':
               case '-':
               case '@':
               case '$':
               case '#':
               case ' ':
               case '/':
               case '&':
                   if (sb.length() > 0) {
                       nextUpperCase = true;
                   }
                   break;
               default:
                   if (nextUpperCase) {
                       sb.append(Character.toUpperCase(c));
                       nextUpperCase = false;
                   } else {
                       sb.append(Character.toLowerCase(c));
                   }
                   break;
           }
       }
       return sb.toString();
   }

没有复杂的正则参与,速度显而快了不少。

End

看一些优秀的开源代码,确实能够了解到一些实用的技巧。这比起自己费劲心力重复制造一些轮子,要高效的多。时间要用在刀刃上,但不是用来切豆腐。


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消