一年又一年,字節(jié)跳動 Lark(飛書) 研發(fā)團(tuán)隊(duì)又雙叒叕開始招新生啦!
【內(nèi)推碼】:GTPUVBA
【內(nèi)推鏈接】:https://job.toutiao.com/s/JRupWVj
【招生對象】:20年9月后~21年8月前 畢業(yè)的同學(xué)
【報名時間】:6.16-7.16(提前批簡歷投遞只有一個月抓住機(jī)會哦?。?/h5>
【畫重點(diǎn)】:提前批和正式秋招不矛盾!面試成功,提前鎖定Offer;若有失利,額外獲得一次面試機(jī)會,正式秋招開啟后還可再次投遞。
點(diǎn)擊進(jìn)入我的博客
字符串操作是計算機(jī)程序設(shè)計中最常見的行為
13.1 不可變String
String底層是由char[]實(shí)現(xiàn)的,是不可變的。
看起來會改變String的方法,實(shí)際上都是創(chuàng)建了一個新的String對象,任何指向它的引用都不可能改變它本身的值。
13.2 重載“+”與StringBuilder
重載操作符的意思是,一個操作符被用于不同的類時,被賦予類特殊的含義(String的+和+=是Java中僅有的兩個重載過的操作符,而且Java不允許程序員重載操作符)。
由于String的不可變性,如果你通過多個String相加生成一個String的時候,就需要產(chǎn)生多個中間對象,這造成了一定的效率問題。
StringBuilder的好處
- 使用
String對字符串進(jìn)行操作時,編譯器會自動幫你轉(zhuǎn)成StringBuilder來進(jìn)行操作 - 用
StringBuilder來操作字符串,編譯后的代碼通常會更加簡單,效率更高 - 如果字符串比較簡單,可以使用
String讓編譯器為你構(gòu)造最終的字符串結(jié)果;如果要在循環(huán)中使用字符串,那么最好自己創(chuàng)建一個StringBuilder。
13.3 無意識的遞歸
@Override
public String toString() {
return "Test" + this;
}
上述代碼中,由于字符串在拼接的時候會自動調(diào)用toString()方法,所以會無意思造成遞歸。
如果你想打印對象的內(nèi)存地址,應(yīng)該調(diào)用Object.toString()方法
13.4 String上的操作
略
13.5 格式化輸出
13.5.1 System.out.printf()
System.out.printf("%d%n", 123)這種輸入方式來自于C,使用特殊的占位符來表示數(shù)據(jù)將來的位置,這些占位符稱作格式修飾符。
13.5.2 System.out.format()
跟System.out.printf()是相同的。
13.5.3 Formatter類
在Java中,所有新的格式化功能都由java.util.Formatter類處理。
Formatter的構(gòu)造器經(jīng)過重載可以接受多種輸出目的地,不過最常用的還是PrintStream、OutputStream和File。
13.5.4 格式化說明符
%[argument_index$] [flags] [width] [.precision] conversion
- 可選的argument_index是一個十進(jìn)制整數(shù),用于表明參數(shù)在參數(shù)列表中的位置。第一個參數(shù)由
1$引用,第二個參數(shù)由2$引用,依此類推(不要忘記$)。 - 可選flags是修改輸出格式的字符集。有效標(biāo)志集取決于轉(zhuǎn)換類型。
- 可選width是一個非負(fù)十進(jìn)制整數(shù),表明要向輸出中寫入的最少字符數(shù),不足則用空格代替。默認(rèn)數(shù)據(jù)是右對齊,可以通過
-實(shí)現(xiàn)左對齊。 - 可選precision是一個非負(fù)十進(jìn)制整數(shù),通常用來限制最大字符數(shù)。特定行為取決于轉(zhuǎn)換類型。
- 所需conversion是一個表明應(yīng)該如何格式化參數(shù)的字符。給定參數(shù)的有效轉(zhuǎn)換集取決于參數(shù)的數(shù)據(jù)類型。
13.5.5 Formatter轉(zhuǎn)換

13.5.6 String.format()
該方法可以接受Formatter.format()方法一樣的參數(shù),但返回一個String對象。
13.6 正則表達(dá)式
正則表達(dá)式是一種強(qiáng)大而靈活的文本處理工具。使用正則表達(dá)式,我們能夠以編程的方式,構(gòu)造復(fù)雜的文本模式,并對輸入的字符串進(jìn)行搜索。一旦找到了匹配這些模式的部分,你就能夠隨心所欲地對它們進(jìn)行處理。
13.6.1 基礎(chǔ)
正則表達(dá)式就是以某種方式來描述字符串。
Java和其他語言對反斜線\的處理不同
- 正常反斜線
\:我們需要的就是一個單純的反斜線,但Java(包括其他語言)中,反斜線也被用來當(dāng)作轉(zhuǎn)義字符,所以不能直接使用 - 文藝反斜線
\\:第一個反斜線表示轉(zhuǎn)移,第二個表示正常的反斜線 - Java二逼反斜線
\\\\:在正則表達(dá)式中,反斜線也需要轉(zhuǎn)義,這是如果要插入一條反斜線這需要這種寫法。四個反斜線的作用其實(shí)是兩兩一組,第一組的反斜線作為轉(zhuǎn)義符,第二組的反斜線是正常要插入的反斜線。
String中內(nèi)建的正則匹配方法
- String#matches()
- String#split()
- String#replaceFirst()
- String#replaceAll()
13.6.2 創(chuàng)建正則表達(dá)式
正則表達(dá)式完整構(gòu)造子列表,請參考java.util.regex.Pattern。
字符

字符類

邏輯操作符

邊界匹配符

13.6.3 量詞
量詞:描述了一個模式吸收輸入文本的方式:
- 貪婪型:默認(rèn)設(shè)置,貪婪表達(dá)式會為所有可能的模式發(fā)現(xiàn)盡可能多的匹配,導(dǎo)致此問題的一個經(jīng)典理由就是假定我們的模式僅能匹配第一個可能的字符組,如果它是貪婪的,那么它會繼續(xù)往下匹配;
- 勉強(qiáng)型:在貪婪型基礎(chǔ)上添加
?,這個量詞匹配滿足模式所需的最少字符數(shù),又稱作最少匹配; - 占有型:在貪婪型基礎(chǔ)上添加
+,目前這種類型的量詞只有在Java中才可用并且也更高級,當(dāng)正則表達(dá)式被應(yīng)用于字符串時,它會產(chǎn)生相當(dāng)多的狀態(tài)以便在匹配失敗時可以回溯,而占有型量詞并不保存這些中間狀態(tài),因此它們可以防止回溯,它們被用來防止正則表達(dá)式失控,因此可以讓正則表達(dá)式執(zhí)行起來更有效。
三種模式對比
13.6.4 Pattern和Matcher
由于String類功能有限,所以可以通過java.util.regex包下的類實(shí)現(xiàn)更加復(fù)雜的功能
一般使用方法
// 1.構(gòu)建Pattern對象
Pattern pattern = Pattern.compile("1[0-9]{10}");
// 2.構(gòu)建Matcher對象
Matcher matcher = pattern.matcher("18888888888");
// 3.使用Matcher方法
System.out.println(matcher.matches());
Pattern方法
// 構(gòu)建Pattern對象
Pattern pattern = Pattern.compile(regex);
// 將字符串按照正則表達(dá)式分割
pattern.split("18888888888");
// 生成Matcher對象判斷是否匹配
pattern.matcher("18888888888");
// 直接驗(yàn)證正則表達(dá)式和字符串是否匹配
Pattern.matches("1[0-9]{10}", "18888888888");
Pattern標(biāo)記
Pattern類的compile()方法還有另一個版本,它接受一個標(biāo)記參數(shù)數(shù),以調(diào)整匹配的行為:
Pattern Pattern.compile(String regex,int flag);。其中的flag來自以下Pattern類中的常量:

Matcher方法
組是用括號劃分的正則表達(dá)式,可以根據(jù)組的編號來引用某個組。組號為0表示整個表達(dá)式,組號1表示被第一對括號括起的組,依此類推。因此在下面這個表達(dá)式:A(B(C))D中有三個組,組0是ABCD,組1是BC,組2是C。
// 整個字符串是否滿足表達(dá)式
matcher.matches();
// 判斷字符串中是否包含表達(dá)式
matcher.lookingAt();
// 遍歷字符串
matcher.find();
matcher.find(int start);
// 返回前一次匹配的結(jié)果
matcher.group();
matcher.groupCount();
// 返回前一次匹配操作中尋找到的組的起始索引
matcher.start();
// 返回前一次匹配操作中尋找到的組的最后一個字符加一的值
matcher.end();
// 替換所有
matcher.replaceAll();
// 替換第一個
matcher.replaceFirst();
// 漸進(jìn)式的替換
matcher.appendReplacement();
// 將現(xiàn)在Matcher用于一個新的字符串
matcher.reset();
13.7 掃描輸入
到日前為止,從文件或標(biāo)準(zhǔn)輸入讀取數(shù)據(jù)還是一件相當(dāng)痛普的事情。終于,Java SE5新增了Scanner類,它可以大大減輕掃描輸入的工作負(fù)擔(dān)。
Scanner有多個重載的構(gòu)造器,可以接受File、Path、InputStream、String和Readable對象。Readable是Java SE5中新加入的一個接口,表示“具有read()方法的某種東西”。
13.7.1 Scanner的定界符
在默認(rèn)的情況下,Scanner根據(jù)空白字符對輸入進(jìn)行分詞,但是你可以用正則表達(dá)式指定自己所需的定界符:scanner.useDelimiter();。還有一個delimiter()方法,用來返回當(dāng)前正在作為定界符使用的Pattern對象。
13.7.2 用正則表達(dá)式掃描
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext("(\\d+)@(\\w+)\\.(\\w+)")) {
scanner.next("(\\d+)@(\\w+)\\.(\\w+)");
MatchResult result = scanner.match();
System.out.println("號碼:" + result.group(1));
System.out.println("域名:" + result.group(2));
System.out.println("后綴:" + result.group(3));
}
Scanner可以接受Pattern作為參數(shù),可以掃描復(fù)雜的數(shù)據(jù)。
配合正則表達(dá)式掃描時要注意:它僅僅針對下一個輸入分詞進(jìn)行匹配,如果你的正則表達(dá)式中含有定界符,那永遠(yuǎn)都不可能匹配成功。
13.8 StringTokenizer
已過時!
