簡體   English   中英

為什么在空字符串上“拆分”會返回一個非空數組?

[英]Why does "split" on an empty string return a non-empty array?

拆分空字符串返回大小為 1 的數組:

scala> "".split(',')
res1: Array[String] = Array("")

考慮這將返回空數組:

scala> ",,,,".split(',')
res2: Array[String] = Array()

請解釋:)

如果將橙色分成零次,則只有一個橙色。

拆分空字符串會將空字符串作為第一個元素返回。 如果在目標字符串中找不到分隔符,則將獲得一個大小為1的數組,該數組包含原始字符串,即使它是空的。

Java和Scala拆分方法分兩步運行,如下所示:

  • 首先,通過分隔符拆分字符串。 自然的結果是,如果字符串不包含分隔符,則返回僅包含輸入字符串的單個數組,
  • 其次, 刪除所有最右邊的空字符串。 這就是",,,".split(",")返回空數組的原因。

根據這個, "".split(",")應該是一個空數組,因為第二步,對嗎?

這應該。 不幸的是,這是一個人為引入的角落案例。 這很糟糕,但至少記錄java.util.regex.Pattern ,如果你還記得看看文檔:

對於n == 0,結果與n <0相同,但不會返回尾隨空字符串。 (注意,輸入本身是空字符串的情況是特殊的,如上所述,並且limit參數不適用於那里。)

解決方案1:始終傳遞-1作為第二個參數

所以,我建議你總是傳遞n == -1作為第二個參數(這將跳過上面的第二步),除非你明確知道你想要實現什么/你確定空字符串不是你的程序會得到一個輸入。

解決方案2:使用Guava Splitter類

如果您已在項目中使用Guava,則可以嘗試使用Splitter(文檔)類。 它有一個非常豐富的API,使您的代碼非常容易理解。

Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"

出於同樣的原因

",test" split ','

",test," split ','

將返回一個大小為2的數組。第一個匹配之前的所有內容都將作為第一個元素返回。

"a".split(",") - > "a"因此"".split(",") - > ""

在所有編程語言中,我知道空字符串仍然是有效的字符串。 因此,使用任何分隔符進行拆分將始終返回單個元素數組,其中該元素是空字符串。 如果它是一個null(非空)字符串,那么這將是一個不同的問題。

這種split行為繼承自Java,無論好壞......
Scala不會覆蓋String原語中的定義。

注意,您可以使用limit參數來修改行為

limit參數控制模式的應用次數,因此會影響結果數組的長度。 如果限制n大於零,那么模式將最多應用n - 1次,數組的長度將不大於n,並且數組的最后一個條目將包含除最后一個匹配分隔符之外的所有輸入。 如果n是非正數,那么模式將被應用盡可能多的次數,並且數組可以具有任何長度。 如果n為零,那么模式將被應用盡可能多的次數,該數組可以具有任何長度,並且將丟棄尾隨的空字符串。

即你可以設置limit=-1來獲得(所有?)其他語言的行為:

@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")

@ ",a,,b,,".split(",", -1)  // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")

似乎眾所周知Java行為令人困惑但是:

從至少Java 5到Java 8可以觀察到上述行為。

JDK-6559590中拆分空字符串時,嘗試更改行為以返回空數組。 然而,它很快就在JDK-8028321中被還原,當它在各個地方引起回歸時。 這一變化從未進入最初的Java 8版本。

注意:split方法從一開始就不是Java(它不在1.0.2中 ),但實際上至少存在1.4(例如,參見2002年的JSR51 )。 我還在調查......

目前還不清楚為什么Java首先選擇了這個(我懷疑它最初是一個“邊緣案例”中的疏忽/錯誤),但現在已經不可逆轉地融入語言中,所以它仍然存在

拆分字符串時,空字符串沒有特殊狀態。 你可以使用:

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())

使用這個 Function,

public static ArrayList<String> split(String body) {
    return new ArrayList<>(Arrays.asList(Optional.ofNullable(body).filter(a->!a.isEmpty()).orElse(",").split(",")));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM