Java字符串與正則表達式操作方法詳解
寫在前面
1、String在java源碼中是怎么實現的?
2、什么是正則表達式的DFA自動機和NFA自動機?
1、String
1.1、String底層實現
Java 6及以前版本,通過char數組,每個char占用兩個字節(jié),使得String能夠很好地處理Unicode。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char[] value;
private int offset;
private int count;
// ...其他成員和方法
}
Java 7至Java 8版本,offset和count兩個變量被移除,String.substring不再共享char[],解決內存可能泄漏問題。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char[] value;
// ...其他成員和方法
}
Java9開始,把char[]改成了byte[] + coder(編碼標識)
1.2、str="abc"和new String(“abc”)的區(qū)別
- str=“abc”
會先檢查"abc"在不在常量池,在就不創(chuàng)建了,直接拿引用 - new String(“abc”)
先將”abc“放入常量池,再將其引用傳給new的String
1.3、使用+拼接字符串
使用+拼接字符串,代碼編譯后,會被替換成StringBuilder。并且每+的一個字符串都可能被new一個新的StringBuilder,所以建議少用+,直接用StringBuilder
1.4、如何使用String.intern節(jié)約內存
String a = new String(“a123”).intern();
當調用intern()時,會先查看常量池中是否已有字符串”a123“, 所以當多次用到”a123“時,使用String.intern不會再創(chuàng)建新的字符串,從而節(jié)約內存。
1.5、分割字符,split()和indexOf()用哪個
split()使用正則表達式實現,正則表達式性能是比較不穩(wěn)定的。
indexOf()能分割時盡量用indexOf()
2、正則表達式
2.1、DFA和NFA
| 正則表達式引擎 | 構造代價 | 執(zhí)行效率 | 優(yōu)勢 |
|---|---|---|---|
| NFA | 小 | 低 | 支持更多,如group、環(huán)視、占有有限量詞 |
| DFA | 大 | 高 |
NFA 自動機回溯
str = "arrrc"
reg = "ar{1,3}c"
自動回溯會先匹配arrr,匹配到c,發(fā)現不是r,就回溯到最后一個r,用reg的c去繼續(xù)匹配
2.2、怎么減少回溯?
1、貪婪模式
如上述例子就是貪婪模式
2、懶惰模式
str = "arrrc"
reg = "ar{1,3}?c"
懶惰模式會先匹配ar,發(fā)現已經有一個r了,就開始用c接著匹配
3、獨占模式
str = "arrc"
reg = "ar{1,3}+rc"
獨占模式會先匹配ar,發(fā)現已經有一個r了,就開始用rc接著匹配,不會回溯
下面這種獨占模式會回溯
str = "arrc"
reg = "ar{1,3}+c"
獨占模式會先匹配ar,發(fā)現已經有一個r了,就開始用c接著匹配,匹配失敗回溯
總結:
1、少用貪婪模式,多用獨占模式
2、減少分支選擇,如將”(abcd|abef)“替換為”ab(cd|ef)“
3、減少捕獲嵌套。
捕獲組: 一個 ()里面的就是一個不獲取
非捕獲組:一個(?:EXP)就是一個非捕獲組
str = "<input id=1>文本</input>" reg = "(<input.*?)(.*?)(</input)" # 上面reg包含了3個捕獲組,所以如果輸出捕獲結果會有整個匹配到的內容+括號里面的,4組字符串 str = "<input id=1>文本</input>" reg = "(?:<input.*?)(.*?)(?:</input)" # 上面reg包含了1個捕獲組,所以如果輸出捕獲結果會有整個匹配到的內容+捕獲組括號里面的,2組字符串
到此這篇關于Java字符串與正則表達式操作的文章就介紹到這了,更多相關Java字符串與正則表達式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java中構造方法set/get和toString的使用詳解
這篇文章主要介紹了Java中構造方法set/get和toString的使用詳解,構造函數的最大作用就是創(chuàng)建對象時完成初始化,當我們在new一個對象并傳入參數的時候,會自動調用構造函數并完成參數的初始化,需要的朋友可以參考下2019-07-07
Spring使用Redis限制用戶登錄失敗的次數及暫時鎖定用戶登錄權限功能
這篇文章主要介紹了Spring使用Redis限制用戶登錄失敗的次數及暫時鎖定用戶登錄權限功能,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2024-02-02
SpringBoot項目整合MybatisPlus并使用SQLite作為數據庫的過程
SQLite是一個緊湊的庫,啟用所有功能后,庫大小可以小于 750KiB, 具體取決于目標平臺和編譯器優(yōu)化設置, 內存使用量和速度之間需要權衡,這篇文章主要介紹了SpringBoot項目整合MybatisPlus并使用SQLite作為數據庫,需要的朋友可以參考下2024-07-07
深入理解Java中的synchronized 和 ReentrantLock 底層原理
synchronized和ReentrantLock是Java中最核心的兩種鎖實現,前者是JVM內置鎖(隱式鎖),后者是JUC顯式鎖(基于AQS 框架),本文給大家介紹Java中的synchronized和ReentrantLock底層原理,感興趣的朋友跟隨小編一起看看吧2025-11-11

