String의 메서드 중 split()을 사용하던 중 오류가 발생했다.
String str = "test,,";
String[] split = str.split(",");
Arrays.stream(split).forEach(System.out::println);
System.out.println("split.length = " + split.length);
위 코드를 실행했을 때, 결과로 split에 "test", "", ""가 들어있을줄 알았다.
하지만 결과는 아래와 같이 나왔다.

split에 "test" 한개만 담긴 것이다.(빈문자열("")이 무시되었다!)
split(String regex) 메서드의 안에는 이렇게 생겼다.
public String[] split(String regex) {
return split(regex, 0);
}
split(String regex)의 내부는 다시 split(String regex, int limit)로 이어진다.
public String[] split(String regex, int limit) {
/* fastpath if the regex is a
(1)one-char String and this character is not one of the
RegEx's meta characters ".$|()[{^?*+\\", or
(2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter.
*/
char ch = 0;
if (((regex.length() == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
(regex.length() == 2 &&
regex.charAt(0) == '\\' &&
(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
boolean limited = limit > 0;
ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
int last = length();
list.add(substring(off, last));
off = last;
break;
}
}
// If no match was found, return this
if (off == 0)
return new String[]{this};
// Add remaining segment
if (!limited || list.size() < limit)
list.add(substring(off, length()));
// Construct result
int resultSize = list.size();
if (limit == 0) {
while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
resultSize--;
}
}
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
return Pattern.compile(regex).split(this, limit);
}
split(String regex, int limit)의 내부를 다시 들여다보면 다음과 같지만 우리는 limit에 대해서만 생각해보자.
분리 기준 문자열인 regex외에 limit에 의해 동작하는 방식은 3가지가 있다.
limit 인자를 적지 않았을 때, limit가 0인 것으로 간주하고 실행된다. 그래서 limit를 적지 않은 split(String regex)의 내부를 들여다봤을 때, split(String regex, 0)으로 이어진 것이다.
limit가 0일 경우, split()을 통해 분리한 문자열이 빈 문자열이 아닌 문자열뒤에 나오는 모든 빈 문자열을 무시한다.
String str = "test,bcd,,,";
String[] split = str.split(",");
Arrays.stream(split).forEach(System.out::println);
System.out.println("split.length = " + split.length);
위 코드를 실행해보면 "bcd"뒤에 모든 빈 문자열을 무시한 아래와 같은 결과가 나온다.

limit가 0보다 클 경우, 문자열 분리는 limit만큼만 진행한다.
String str = "test,abc,bcd,,,";
String[] split = str.split(",", 2);
Arrays.stream(split).forEach(System.out::println);
System.out.println("split.length = " + split.length);
split 인자에 2를 넣어줬으니 아래와 같이 문자열 분리를 2개만 진행한다.

limit가 0보다 작을 경우, 분리 기준에 의한 분리된 모든 문자열을 나타내준다.
String str = "test,abc,bcd,,,";
String[] split = str.split(",", -1);
Arrays.stream(split).forEach(System.out::println);
System.out.println("split.length = " + split.length);
빈 문자열까지 모두 split에 저장했기 때문에 length가 6이 나온걸 볼 수 있다.

##Reference
https://velog.io/@junho5336/String.split%EC%9D%98-limit