Perilaku String.split
(yang memanggil Pattern.split
) berubah antara Java 7 dan Java 8.
Dokumentasi
Membandingkan antara dokumentasi Pattern.split
di Java 7 dan Java 8 , kami mengamati klausa berikut ditambahkan:
Jika ada kecocokan lebar-positif di awal urutan masukan, maka substring utama yang kosong disertakan di awal larik yang dihasilkan. Kecocokan lebar-nol di awal, namun tidak pernah menghasilkan substring depan yang kosong.
Klausul yang sama juga ditambahkan String.split
di Java 8 , dibandingkan dengan Java 7 .
Implementasi referensi
Mari kita bandingkan kode Pattern.split
implemetasi referensi di Java 7 dan Java 8. Kode tersebut diambil dari grepcode, untuk versi 7u40-b43 dan 8-b132.
Jawa 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);
}
Jawa 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);
}
Penambahan kode berikut di Java 8 mengecualikan kecocokan panjang-nol di awal string input, yang menjelaskan perilaku di atas.
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;
}
Menjaga kompatibilitas
Mengikuti perilaku di Java 8 ke atas
Untuk membuat split
berperilaku secara konsisten di seluruh versi dan kompatibel dengan perilaku di Java 8:
- Jika ekspresi reguler Anda bisa cocok dengan string panjang-nol, cukup tambahkan
(?!\A)
di akhir ekspresi reguler dan bungkus ekspresi reguler asli dalam grup non-penangkap (?:...)
(jika perlu).
- Jika ekspresi reguler Anda tidak cocok dengan string panjang-nol, Anda tidak perlu melakukan apa pun.
- Jika Anda tidak tahu apakah ekspresi reguler bisa cocok dengan string panjang-nol atau tidak, lakukan kedua tindakan di langkah 1.
(?!\A)
memeriksa bahwa string tidak berakhir di awal string, yang berarti bahwa pertandingan tersebut adalah pertandingan kosong di awal string.
Mengikuti perilaku di Java 7 dan sebelumnya
Tidak ada solusi umum untuk membuat split
kompatibel dengan Java 7 dan sebelumnya, selain mengganti semua instance split
untuk mengarah ke implementasi kustom Anda sendiri.
s.split("(?!^)")
sepertinya berhasil.