Java
裏字符串表示字符的不可變序列,建立後就不能更改。在咱們平常的工做中,字符串的使用很是頻繁,熟練的對其操做能夠極大的提高咱們的工做效率,今天要介紹的主角是 Google
開源的一個核心 Java
庫 Guava,它提供了集合類型、不可變的集合、併發、I / O、緩存、字符串等許多實用功能。在本文中,咱們將學習使用 Guava
中的 Strings
和 Splitter
字符串操做工具類。html
Google Guava
會同步到 Maven Central 中,因此,若是你是 Maven
項目的話只須要在 pom.xml
文件中引入以下依賴便可:java
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>28.2-jre</version> </dependency>
對於 Gradle
項目在 build.gradle
中引入以下依賴便可:git
compile group: 'com.google.guava', name: 'guava', version: '28.2-jre'
<!--more-->github
PS:28.2-jre 是編寫本文時的最新版本,你能夠從
Maven Central 中查看當前的最新版本。
正則表達式
Google Guava
提供了不少實用的靜態方法,這些能夠解決開發人員在開發中所要完成的一些重複任務。固然,這個工做咱們也能夠本身作,可是引入類庫它會下降錯誤發生的可能性,畢竟這些類庫都是已經通過多年的生產驗證。好比類庫中 Strings
提供的一個方法 commonPrefix
,它接受兩個字符串並返回兩個字符串之間的公共前綴(eg: abcd
和 abef
返回 ab
)。你能夠在腦子裏想象一下在應用程序代碼中面臨這樣的要求時,本身要如何編寫代碼來完成該操做,要本身實現這個功能,仍是須要花費一些時間的,同時還須要考慮到各類邊界異常狀況。這就是類庫提供給咱們的最大價值之一,因此當咱們須要的某種功能能夠做爲一種工具方法使用時,首先應該去尋找一些已存在的類庫並去熟練使用的它們,而不是本身去實現。總結起來使用類庫有以下幾個緣由:緩存
Google Guava
類庫有人已經對其進行了完全的測試,bug
出現的機率會比咱們本身實現的小不少Google Guava
的一部分,已經存在各類測試用例,用於測試實用程序的實現。若是咱們本身編寫代碼實現的話,可能還要去編寫和維護它們的測試。Google Guava
有許多實用的工具類和方法,不可能在一篇文章中都有介紹完,在本文中,只會介紹和字符串操做相關的兩個工具類。首先第一個是 Strings
類,該類提供了操做 String
和 CharSequence
的實用方法。併發
nullToEmpty
方法功能爲:若是傳入的字符串爲 null
,則返回一個空字符串 ""
,不然,返回一個空字符串,不然按原樣返回傳遞的字符串。工具
@Test public void testStringsOfNullToEmpty() { System.out.println(Strings.nullToEmpty("mghio")); // mghio System.out.println(Strings.nullToEmpty("")); // "" System.out.println(Strings.nullToEmpty(null)); // "" System.out.println(Strings.nullToEmpty(null).isEmpty()); // true }
emptyToNull
方法功能爲:它與 nullToEmpty
相反,若是傳入了空字符串,則返回 null
,不然返回原始字符串。學習
@Test public void testStringsOfEmptyToNull() { System.out.println(Strings.emptyToNull("mghio")); // mghio System.out.println(Strings.emptyToNull(null)); // null System.out.println(Strings.emptyToNull("")); // null }
isNullOrEmpty
方法功能爲:若是傳入的字符串爲 null
或爲空,則返回 true
,不然返回 false
。測試
@Test public void testStringsOfIsNullOrEmpty() { System.out.println(Strings.isNullOrEmpty("mghio")); // false System.out.println(Strings.isNullOrEmpty("")); // true System.out.println(Strings.isNullOrEmpty(null)); // true }
這兩個方法有三個參數,分別爲:輸入字符串、最小長度和要填充的字符,它將字符根據須要屢次插入到輸入字符串的開頭,以使輸入字符串的長度等於傳入的最小長度。
@Test public void testStringsOfPadStart() { System.out.println(Strings.padStart("9527", 6, '0')); // 009527 System.out.println(Strings.padStart("123456", 6, '0')); // 123456 }
在第一行代碼中,將兩次填充 0
以使最終的字符串長度等於咱們傳入的最小長度(6)。在第二行代碼中,輸入字符串長度自己具備所需的最小長度,所以未進行填充padEnd
方法和上面這個方法相似,只不過它是在字符的末尾而不是在開始處進行填充。
@Test public void testStringsOfPadEnd() { System.out.println(Strings.padEnd("9527", 6, '0')); // 952700 System.out.println(Strings.padEnd("123456", 6, '0')); // 123456 }
該方法須要傳入一個字符串和一個重複次數 count
,它返回一個由原始字符串組成的字符串,該字符串重複了 count
次。
@Test public void testStringsRepeat() { System.out.println(Strings.repeat("mghio", 3)); // mghiomghiomghio }
commonPrefix
方法返回傳入的兩個字符串之間最大的公共前綴,而 commonSuffix
方法返回傳入兩個字符串之間最大的公共後綴。
@Test public void testStrings() { System.out.println(Strings.commonPrefix("mghio9527", "mghio666")); // mghio System.out.println(Strings.commonSuffix("iammghio", "nicemghio")); // mghio }
Splitter
類提供的功能正如其名(PS:一個好的命名很重要
),它用於根據提供的分割符將字符串拆分爲多個子字符串。咱們能夠經過傳入一個分割符來獲一個 Splitter
的實例,有了分割器以後,咱們能夠根據分割器的配置方式對字符串進行分割。
@Test public void testSplitterOfSplit() { Iterable<String> result = Splitter.on(",").split("m,g,h,i,o"); System.out.println(result); // [m, g, h, i, o] }
上面的例子中使用逗號進行分割,所以,它將傳入的字符串 m,g,h,i,o
拆分爲一個 Iterable <String>
,而後當咱們對其進行迭代遍歷時會輸出 [m, g, h, i, o]
。
如今,咱們來看看得到一個分割器 Splitter
的各類方法。on
方法有各類不一樣的重載版本,它們以字符、字符串或正則表達式做爲分隔符,咱們還能夠將 Pattern
實例做爲字符串傳遞給 onPattern
方法中。
@Test public void testSplitterOfOn() { Splitter wordSplitter = Splitter.on(":;"); // 下面這行輸出結果 [the, text, is, separated, by, colon, semicolon] System.out.println(wordSplitter.split("the:;text:;is:;separated:;by:;colon:;semicolon")); Splitter patternBasedSplitter = Splitter.on(Pattern.compile("\\s+")); System.out.println(patternBasedSplitter.split("abc dmg hio")); // [abc, dmg, hio] System.out.println(Splitter.onPattern("\\s+").split("www mghio cn")); // [www, mghio, cn] }
fixedLength
也是最有用的方法之一,它能夠將字符串分紅給定長度的相等部分,須要注意的是,最後一個部分可能會小於給定的長度。
@Test public void testSplitterOfFixedLength() { Splitter fixedLengthSplitter = Splitter.fixedLength(3); System.out.println(fixedLengthSplitter.split("iammghiojava")); // [iam, mgh, ioj, ava] System.out.println(fixedLengthSplitter.split("https://www.mghio.cn")); // [htt, ps:, //w, ww., mgh, io., cn] }
Splitter
還提供了能夠在更改或修改 Splitter
行爲的經常使用方法。
這個方法能夠從生成的分割器的結果字符串中刪除前面和末尾的空格。
@Test public void testSplitterOfTrimResult() { Splitter commaSplitter = Splitter.on(","); System.out.println(commaSplitter.split("m, g, h, i, o")); // [m, g, h, i, o] Splitter commaSplitterWithTrim = commaSplitter.trimResults(); System.out.println(commaSplitterWithTrim.split("m, g, h, i, o")); // [m, g, h, i, o] }
注意,第一個分割的結果在字符串 g
、 h
、i
、o
以前有一個空格,使用 trimResults
方法後,將去除這些前導空格。
這個方法會從結果中忽略全部空字符串。
@Test public void testSplitterOfOmitEmptyStrings() { Splitter commaSplitter = Splitter.on(","); System.out.println(commaSplitter.split("m,,g,h,i,o")); // [m, , g, h, i, o] Splitter commaSplitterWithNoEmptyString = commaSplitter.omitEmptyStrings(); System.out.println(commaSplitterWithNoEmptyString.split("m,,g,h,i,o")); // [m, g, h, i, o] }
上面的 commaSplitterWithNoEmptyString
會從輸出中刪除空字符串的結果。
這個方法返回與原始分割器等效的分割器,但它會在達到指定的輸入限制後將中止拆分,將後續剩餘結果字符串做爲一項輸出,也就是說,咱們能夠經過的傳入的參數指定結果中存在的最大項目數。須要注意的是:該方法在省略空字符串時,省略的字符串不計算在內。
。
@Test public void testSplitterOfLimit() { Splitter commaSplitter = Splitter.on(","); Splitter limitingCommaSplitter = commaSplitter.limit(3); System.out.println(limitingCommaSplitter.split("i,m,g,h,i,o")); // [i, m, g,h,i,o] }
有一點須要注意,Splitter
是不可變的(這一點和 String
相似),所以,調用它的任何修飾符方法都將返回新的 Splitter
,而且不會修改原始的 Splitter
。
@Test public void testSplitterImmutable() { Splitter splitter = Splitter.on('/'); System.out.println("Before: " + splitter); // Before: com.google.common.base.Splitter@33b37288 splitter.trimResults(); // do nothing System.out.println("First: " + splitter); // First: com.google.common.base.Splitter@33b37288 splitter = splitter.trimResults(); // the returned splitter to be assigned System.out.println("Second: " + splitter); // Second: com.google.common.base.Splitter@77a57272 }
咱們前面已經使用的 split
方法,它返回的是一個 Iterable<String>
對象。而這裏的 splitToList
方法返回一個 List<String>
。因爲分割方法返回的是 Iterable
,所以它是惰性
的。
@Test public void testSplitterOfSplitToList() { Splitter commaSplitter = Splitter.on(","); List<String> result = commaSplitter.splitToList("m,g,h,i,o"); System.out.println(result); // [m, g, h, i, o] }
MapSplitter
顧名思義就是用來將一個將字符串拆分爲 Map
對象的。咱們可使用 withKeyValueSeparator
方法從 Splitter
中獲取 MapSplitter
對象,該方法接收一個字符、字符串或者 Splitter
對象做爲參數。首先,根據原始的分割器將字符串分割爲多個項,而後,使用傳給 withKeyValueSeparator
方法的分割符將各個項分爲 Map
鍵-值對。
@Test public void testSplitterOfWithKeyValueSeparator() { Splitter commaSplitter = Splitter.on(','); Splitter.MapSplitter keyValueSplitter = commaSplitter.withKeyValueSeparator('='); Map<String, String> map = keyValueSplitter.split("name=mghio,blog=mghio.cn"); System.out.println(map); // {name=mghio, blog=mghio.cn} }
從結果能夠看到,它分割爲兩個 entry
(name=mghio
與 blog=mghio.cn
)項,還有一個點須要注意的是:若是咱們在原始的分割器上指定了任何修改器,則它們僅適用於該分割器,而不適用於 MapSplitter
。
@Test public void testSplitterOfWithKeyValueSeparatorAndModifiers() { Splitter originalSplitter = Splitter.on(",").trimResults(); Splitter.MapSplitter keyValueSplitter = originalSplitter.withKeyValueSeparator('='); // 輸出結果:{name =mghio, blog= mghio.cn} System.out.println(keyValueSplitter.split("name =mghio, blog= mghio.cn")); }
由以上結果能夠看出 trimResults
修飾方法僅適用於原始拆分器。所以,blog
開頭的空格已被移除(使用 ,
分割原始字符串時),可是,mghio.cn
開頭的空格不會被移除(使用 =
分割成鍵值時)。
最後須要注意的是:MapSplitter
類被標記爲 @Beta
,這意味着類庫中與 MapSplitter
相關的類和方法是實驗性的,能夠更改(以中斷的方式),甚至未來版本可能刪除。
在本文中,介紹了 Google Guava 庫以及在項目或應用程序中使用它的好處,如何將其導入到咱們的應用程序中使用。而後,介紹了 Guava
庫中對字符串操做工具類(Strings
和 Splitter
)的一些基本用法,固然,這只是冰山一角,Guava
庫還提供了其它不少有用的基礎功能,須要咱們本身去查詢相關文檔學習瞭解,感興趣的朋友能夠去看看它的實現源碼,這個庫的代碼寫得很優雅。
參考