摘要:比如的結果是,長度為,因為首先匹配任意字符,所以原字符串中每一個都是分割符,這就產生了個空字符串,然后默認為,從后往前刪除空字符串,結果就為空。
在 Java 中處理字符串時,split 是一個很常用的操作,但是這一簡單的操作,卻經常有意想不到的結果,就拿Guava庫官方教程中的一個例子來說,",a,,b,".split(",") 的結果是?
1. "", "a", "", "b", "" 2. null, "a", null, "b", null 3. "a", null, "b" 4. "a", "b" 5. None of the above
正確答案應該是 5,以上都不對;正確結果是 ["", "a", "", "b"]。
正是因為 JDK 自帶的 split 這種奇怪的現象,其他開源庫也都給出了自己的 split 方法,如 Apache Commons Lang 和上文中的 Guava 。
split in JDK8String 類包含兩個 split 重載方法,public String[] split(String regex) 和 public String[] split(String regex, int limit),調用前者就相當于默認 limit = 0,而上面的例子中奇怪的現象就和這個 limit 有關。
JDK 文檔中是這么解釋的:
當 limit 即 n 大于 0 時,會返回至多 n 項,最后一項會包含所有未被拆分的部分
當 n 小于 0 時,會返回所有拆分后的結果
當 n 等于 0 時,會返回所有拆分后的結果,但是最后跟著的空字符串會被刪除
由于使用了單參數的 split 方法,n == 0,于是就產生了如上的結果。關于這一部分的 JDK 中的源碼部分如下:
// Construct result int resultSize = list.size(); if (limit == 0) { while (resultSize > 0 && list.get(resultSize - 1).length() == 0) { resultSize--; } }
平常在分析一些具有固定格式的數據時,比如每一行都是 tab 分割的,且有固定列數,那么進行解析時可以使用 s.split(" ", -1) 來進行操作。這樣會保存所有的分割項,包含任意部位的空字符串,比如
":a::b::".split(":", -1) => ["", "a", "", "b", "", ""]
另外一個需要注意的地方是,split 接收的參數是一個正則表達式,這一點經常容易忽略。比如 "a.b.c".split(".") 的結果是 [],長度為 0 ,因為首先 . 匹配任意字符,所以原字符串中每一個都是分割符,這就產生了 6 個空字符串, 然后 limit 默認為 0 ,從后往前刪除空字符串,結果就為空。
split in Commons LangJDK 中的方法畢竟還是簡單了一些,不能滿足我們一些特殊需求,或者說不想使用正則,那么可以使用 Commons Lang 庫中的方法。這些 split 方法有以下特點:
如果沒有指定結果個數,都默認輸出最多項
如果沒有 PreserveAllTokens 后綴,默認將多個連續分割符視為 1 個,不保留任意位置空字符串
比如:
StringUtils.split("::a::b::", ":") => ["a", "b"]
需要注意的是 split(String str, String separatorChars) 方法中第二個參數的意義是每一個字符都被當成分割符,比如:
StringUtils.split(":a:b:", "ab") => [":", ":", ":"]
那么假如我想用 "ab" 整體作為分割符呢,可以使用 splitByWholeSeparator 方法:
StringUtils.splitByWholeSeparator("abcabc","ab") => ["c", "c"]
但這個方法有一個和其他方法表現不一致的地方,它保留了末尾的空字符串,且只保留一個。
StringUtils.splitByWholeSeparator("abb", "bb") => ["a", ""] StringUtils.splitByWholeSeparator("bba", "bb") => ["a"] StringUtils.splitByWholeSeparator("abbbbabbbb", "bb") =>["a", "a", ""]
另外一個我覺得很有用的就是一系列 splitPreserveAllTokens 重載函數了,因為默認輸出所有結果,且保留了空字符串。和 JDK 中的 limit = -1 結果一致,但更易讀一些。
split in Guava假如你已經被上面這些特殊情況都繞暈了,不妨試試 Guava 庫,它沒有提供簡單的一系列重載 split 方法,而是提供了一系列的工廠方法,采用鏈式調用,從而從方法名上就能看出結果,不用苦思冥想到底有沒有陷阱。
Splitter.on(",") .trimResults(CharMatcher.is(",")) .omitEmptyStrings() .limit(2) .split("a,,,,,b,,,,c,,,") => ["a", "b,,,,c"]
除了按照分割符外,還可以按照長度:
Splitter.fixedLength(3).split("abcde") => ["abc", "de"]
不像 JDK 和 Commons Lang 中的返回數組,Guava 返回 Iterable 和 List,而且這個 Iterable 已經重載了 toString,可以方便地進行打印測試。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68045.html
摘要:元組也支持內置函數的參數必須是一個序列字符串列表元組元組有什么用既然中有這么個數據結構,自然就有它的用武之地。 引言 想學爬蟲還是 python 專業啊,之前一直在用 java, 現在決定嘗嘗鮮,使用 python及爬蟲框架來完成網絡數據采集。編程語言之間都是相通的,比如都需要模塊化,引入其他文件來實現功能,使用列表等容器來處理數據,都要使用 json 或 xml 來解析和傳輸數據。你...
摘要:元組也支持內置函數的參數必須是一個序列字符串列表元組元組有什么用既然中有這么個數據結構,自然就有它的用武之地。 引言 想學爬蟲還是 python 專業啊,之前一直在用 java, 現在決定嘗嘗鮮,使用 python及爬蟲框架來完成網絡數據采集。編程語言之間都是相通的,比如都需要模塊化,引入其他文件來實現功能,使用列表等容器來處理數據,都要使用 json 或 xml 來解析和傳輸數據。你...
摘要:字符串在中,萬物皆對象,顯然字符串是對象類型,用表示。其二是聲明為原始字符串如,由開頭引起的字符串就是聲明了后面引號里的東西是原始字符串,在里面放任何字符都表示該字符的原始含義,不需要再用轉義符了。 Python字符串 在Python中,萬物皆對象,顯然字符串是對象類型,用str表示。字符串類型通常用單引號或者雙引號包裹起來。 >>> Hello,world Hello,world >...
摘要:大家好我是小小明,今天給大家演示如何使用直接采集百度指數的數據。本文不演示如何使用自動化工具采集百度指數,為了采集更簡單將直接讀取并解析接口。 大家好我是小小明,今...
摘要:本題要求編寫程序,計算個有理數的和差積商。輸出格式分別在行中按照有理數運算符有理數結果的格式順序輸出個有理數的和差積商。注意輸出的每個有理數必須是該有理數的最簡形式,其中是整數部分,是最簡分數部分若為負數,則須加括號若除法分母為,則輸出。 本題要求編寫程序,計算 2 個有理數的和、差、積、商。 輸入格式:輸入在一行中按照 a1/b1 a2/b2 的格式給出兩個分數形式的有理數,其中分...
閱讀 2586·2021-11-18 10:02
閱讀 1719·2021-09-30 10:00
閱讀 5341·2021-09-22 15:27
閱讀 1218·2019-08-30 15:54
閱讀 3682·2019-08-29 11:13
閱讀 2955·2019-08-29 11:05
閱讀 3331·2019-08-29 11:01
閱讀 579·2019-08-26 13:52