Hành vi của String.split
(mà gọi Pattern.split
) thay đổi giữa Java 7 và Java 8.
Tài liệu
So sánh giữa các tài liệu của Pattern.split
trong Java 7 và Java 8 , chúng tôi tuân thủ các điều khoản sau đây được bổ sung:
Khi có một kết quả khớp có độ rộng dương ở đầu chuỗi đầu vào thì một chuỗi con trống ở đầu dãy kết quả sẽ được đưa vào. Tuy nhiên, một kết quả có độ rộng bằng 0 ở đầu không bao giờ tạo ra chuỗi con đứng đầu trống như vậy.
Mệnh đề tương tự cũng được thêm vào String.split
trong Java 8 , so với Java 7 .
Thực hiện tham khảo
Hãy để chúng tôi so sánh mã của Pattern.split
phép tham chiếu trong Java 7 và Java 8. Mã được truy xuất từ grepcode, cho phiên bản 7u40-b43 và 8-b132.
Java 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);
}
Java 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);
}
Việc bổ sung mã sau trong Java 8 loại trừ khớp có độ dài bằng 0 ở đầu chuỗi đầu vào, điều này giải thích hành vi ở trên.
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;
}
Duy trì khả năng tương thích
Hành vi sau trong Java 8 trở lên
Để thực hiện split
hành vi nhất quán giữa các phiên bản và tương thích với hành vi trong Java 8:
- Nếu regex của bạn có thể khớp với chuỗi có độ dài bằng 0, chỉ cần thêm
(?!\A)
vào cuối regex và bọc regex ban đầu trong nhóm không bắt (?:...)
(nếu cần).
- Nếu regex của bạn không thể khớp với chuỗi có độ dài bằng 0, bạn không cần phải làm gì cả.
- Nếu bạn không biết liệu regex có thể khớp với chuỗi độ dài bằng 0 hay không, hãy thực hiện cả hai thao tác trong bước 1.
(?!\A)
kiểm tra xem chuỗi không kết thúc ở đầu chuỗi, điều này ngụ ý rằng kết hợp là một kết quả trống ở đầu chuỗi.
Hành vi sau trong Java 7 trở về trước
Không có giải pháp chung nào để split
tương thích ngược với Java 7 trở về trước, ngắn gọn là thay thế tất cả các phiên bản của split
để trỏ đến triển khai tùy chỉnh của riêng bạn.
s.split("(?!^)")
dường như hoạt động.