IT

Java 8 분할에서의 결과 배열의 시작 부분에서 빈 부분을 제거하는 이유는 무엇입니까?

lottoking 2020. 8. 8. 12:05
반응형

Java 8 분할에서의 결과 배열의 시작 부분에서 빈 부분을 제거하는 이유는 무엇입니까?


Java 8 이전 에는 빈 분할로 분할 할 때

String[] tokens = "abc".split("");

분할이 분할에서 분할됩니다. |

|a|b|c|

""각 문자 앞뒤에 빈 공간 있기 때문에 입니다. 따라서 결과적으로 처음에는 배열을 생성합니다.

["", "a", "b", "c", ""]

그리고 나중에 후행 빈제거 합니다. ( limit인수에 음수 값을 명시 적으로 제공하지 않습니다. ) 결국 반환됩니다.

["", "a", "b", "c"]

Java 8에서는 중복되는 것입니다. 이제 우리가 사용할 때

"abc".split("")

["a", "b", "c"]대신 배열 ["", "a", "b", "c"]가져옵니다. 그러나이 이론은 실패합니다.

"abc".split("a")

start에 빈 곳이있는 배열을 반환합니다 ["", "bc"].

Java 8에서 분할 규칙이 어떻게 변경되었는지 설명 할 수 있습니까?


String.split(를 호출하는 Pattern.split) 동작은 Java 7과 Java 8간에 변경됩니다.

선적 서류 비치

의 문서 사이의 비교 Pattern.split자바 (7)자바 (8) , 우리는 다음과 같은 조항을 준수하는 것으로 추가되는 추가되는 내용 :

입력 시퀀스의 시작 부분에 양의 너비가 일치하면 결과 배열의 시작 부분에 빈 선행 부분에 포함됩니다. 그러나 처음에 너비가 0 인 일치는 선행 하위 디렉토리를 생성하지 않습니다.

같은 절은 또한 추가 String.split자바 (8) 에 비해, 자바 7 .

참조 구현

Pattern.splitJava 7과 Java 8에서 참조 구현 코드를 비교해 보겠습니다 . 코드는 버전 7u40-b43 및 8-b132에 대해 grepcode에서 검색됩니다.

자바 7

public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);

    // Add segments before each match found
    while(m.find()) {
        if (!matchLimited || matchList.size() < limit - 1) {
            String match = input.subSequence(index, m.start()).toString();
            matchList.add(match);
            index = m.end();
        } else if (matchList.size() == limit - 1) { // last one
            String match = input.subSequence(index,
                                             input.length()).toString();
            matchList.add(match);
            index = m.end();
        }
    }

    // If no match was found, return this
    if (index == 0)
        return new String[] {input.toString()};

    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
        matchList.add(input.subSequence(index, input.length()).toString());

    // Construct result
    int resultSize = matchList.size();
    if (limit == 0)
        while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
            resultSize--;
    String[] result = new String[resultSize];
    return matchList.subList(0, resultSize).toArray(result);
}

자바 8

public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);

    // Add segments before each match found
    while(m.find()) {
        if (!matchLimited || matchList.size() < limit - 1) {
            if (index == 0 && index == m.start() && m.start() == m.end()) {
                // no empty leading substring included for zero-width match
                // at the beginning of the input char sequence.
                continue;
            }
            String match = input.subSequence(index, m.start()).toString();
            matchList.add(match);
            index = m.end();
        } else if (matchList.size() == limit - 1) { // last one
            String match = input.subSequence(index,
                                             input.length()).toString();
            matchList.add(match);
            index = m.end();
        }
    }

    // If no match was found, return this
    if (index == 0)
        return new String[] {input.toString()};

    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
        matchList.add(input.subSequence(index, input.length()).toString());

    // Construct result
    int resultSize = matchList.size();
    if (limit == 0)
        while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
            resultSize--;
    String[] result = new String[resultSize];
    return matchList.subList(0, resultSize).toArray(result);
}

Java 8에서 다음 코드를 추가하면 위의 동작을 설명하는 입력 절차의 시작 부분에서 길이가 0 인 일치 항목이 제외됩니다.

            if (index == 0 && index == m.start() && m.start() == m.end()) {
                // no empty leading substring included for zero-width match
                // at the beginning of the input char sequence.
                continue;
            }

유지

Java 8 이상에서 다음 동작

확인 결과 확인 split자바 8의 행동 버전에서 호환 동작합니다. :

  1. 정규식 -length가 0 문자열과 일치 여부 인 할 수있는 경우 정규식 끝에 추가 (?!\A)하고 필요한 경우 non-캡처 그룹으로 원래 정규식을 래핑합니다 .(?:...)
  2. 정규식 -length가 0 문자열과 일치 여부 인 할 수없는 경우 아무것도 할 필요가 없습니다.
  3. 정규식이 길이가 0 인 문자열과 일치 할 수 있는지 여부를 모르는 경우 1 단계의 두 작업을 모두 수행하십시오.

(?!\A) 문자열이 문자열 시작 부분에서 끝나지 않는지 확인합니다. 이는 일치 항목이 문자열 시작 부분에서 비어 있음을 의미합니다.

Java 7 및 이전 버전에서 다음 동작

splitJava 7 및 이전 버전과의 역 호환성 을 만드는 일반적인 솔루션은 없습니다. 모든 인스턴스를 split사용자 정의 구현 으로 바꾸는 것보다 부족 합니다.


이것은의 문서에 지정되어 split(String regex, limit)있습니다.

이 문자열의 시작 부분에 양의 너비가 일치하면 결과 배열의 시작 부분에 빈 선행 부분 문자열이 포함됩니다. 그러나 처음에 너비가 0 인 일치는 이러한 빈 선행 하위 문자열을 생성하지 않습니다.

에서 "abc".split("")선도적 인 빈 문자열이 결과 배열에 포함되지 않습니다 있도록 시작 부분에 폭 제로 일치를 얻었다.

그러나 분할 할 때 두 번째 스 니펫 "a"에서 양의 너비 일치 (이 경우 1)를 얻었으므로 빈 선행 하위 문자열이 예상대로 포함됩니다.

(관련없는 소스 코드 제거)


split()Java 7에서 Java 8로 문서가 약간 변경되었습니다. 특히 다음 명령문이 추가되었습니다.

이 문자열의 시작 부분에 양의 너비가 일치하면 결과 배열의 시작 부분에 빈 선행 부분 문자열이 포함됩니다. 그러나 처음에 너비가 0 인 일치는 이러한 빈 선행 하위 문자열을 생성하지 않습니다.

(강조 내)

빈 문자열 분할은 처음에 너비가 0 인 일치를 생성하므로 위에 지정된 내용에 따라 결과 배열의 시작 부분에 빈 문자열이 포함되지 않습니다. 반대로 분할하는 두 번째 예제 는 문자열의 시작 부분에 양의 너비 일치를 "a"생성 하므로 실제로 결과 배열의 시작 부분에 빈 문자열이 포함됩니다.

참고 URL : https://stackoverflow.com/questions/22718744/why-in-java-8-split-sometimes-removes-empty-strings-at-start-of-result-array

반응형