[java] 빈 문자열에서 “분할”이 비어 있지 않은 배열을 반환하는 이유는 무엇입니까?

빈 문자열로 분할하면 크기 1의 배열이 반환됩니다.

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

이것이 빈 배열을 반환한다는 것을 고려하십시오.

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

설명 해주십시오 🙂



답변

같은 이유로

",test" split ','

",test," split ','

크기 2의 배열을 반환합니다. 첫 번째 일치 이전의 모든 항목이 첫 번째 요소로 반환됩니다.


답변

오렌지를 0 번 분할하면 정확히 한 조각 인 오렌지가 있습니다.


답변

Java 및 Scala 분할 메서드는 다음과 같은 두 단계로 작동합니다.

  • 먼저 구분 기호로 문자열을 분할합니다. 자연스러운 결과는 문자열에 구분 기호가 포함되지 않은 경우 입력 문자열 만 포함하는 단일 배열이 반환됩니다.
  • 둘째, 가장 오른쪽에있는 빈 문자열을 모두 제거합니다. 이것이 ",,,".split(",")빈 배열을 반환 하는 이유 입니다.

이것에 따르면 "".split(",")두 번째 단계 때문에 결과 는 빈 배열이어야합니다.

그래야한다. 불행히도 이것은 인위적으로 도입 된 코너 케이스입니다. 그리고 그것은 나쁘지만 문서java.util.regex.Pattern살펴 보는 것을 기억한다면 적어도 문서화 되어 있습니다.

n == 0의 경우 결과는 n <0과 같지만 후행 빈 문자열이 반환되지 않습니다. (입력 자체가 빈 문자열 인 경우는 위에서 설명한 것처럼 특별하며 제한 매개 변수가 적용되지 않습니다.)

솔루션 1 : 항상 두 번째 매개 변수로 -1을 전달하십시오.

따라서 n == -1달성하려는 내용을 구체적으로 알고 있거나 프로그램이 입력으로 얻을 수있는 빈 문자열이 아니라고 확신하지 않는 한 항상 두 번째 매개 변수로 전달하는 것이 좋습니다 (위의 2 단계를 건너 뜁니다).

해결 방법 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"


답변

빈 문자열을 분할하면 빈 문자열이 첫 번째 요소로 반환됩니다. 대상 문자열에 구분 기호가 없으면 비어 있더라도 원래 문자열을 보유하는 크기 1의 배열을 얻습니다.


답변

"a".split(",")-> "a"
따라서
"".split(",")->""


답변

모든 프로그래밍 언어에서 빈 문자열이 여전히 유효한 문자열이라는 것을 알고 있습니다. 따라서 구분 기호를 사용하여 분할하면 해당 요소가 빈 문자열 인 단일 요소 배열이 항상 반환됩니다. null (공백이 아님) 문자열이면 다른 문제가됩니다.


답변

split동작은 좋든 나쁘 든 Java에서 상속됩니다.
스칼라는 String기본 형식 의 정의를 재정의하지 않습니다 .

당신이 할 수있는, 주 사용 limit동작을 수정하기위한 인수를 :

limit 매개 변수는 패턴이 적용되는 횟수를 제어하므로 결과 배열의 길이에 영향을줍니다. 한계 n이 0보다 크면 패턴은 최대 n-1 회 적용되고 배열의 길이는 n보다 크지 않으며 배열의 마지막 항목에는 마지막 일치 구분 기호를 초과하는 모든 입력이 포함됩니다. n이 양수가 아닌 경우 패턴이 가능한 한 많이 적용되고 배열의 길이는 제한되지 않습니다. n이 0이면 패턴이 가능한 한 많이 적용되고 배열은 임의의 길이를 가질 수 있으며 후행 빈 문자열은 삭제됩니다.

즉, 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 이상에 있습니다 (예 : JSR51 circa 2002 참조 ). 아직 조사 중입니다 …

분명하지 않은 것은 Java가 처음에 이것을 선택한 이유입니다 (원래 “가장자리 사건”에서 감독 / 버그 였다고 의심합니다).하지만 이제는 그 언어에 돌이킬 수없이 구워 져서 그대로 남아 있습니다 .