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.splittrong 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.splittrong 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.splitphé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 splithà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 để splittươ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.