Podział łańcucha Java usunął puste wartości

286

Próbuję podzielić wartość za pomocą separatora. Ale znajduję zaskakujące wyniki

String data = "5|6|7||8|9||";
String[] split = data.split("\\|");
System.out.println(split.length);

Spodziewam się uzyskać 8 wartości. [5,6,7, EMPTY, 8,9, EMPTY, EMPTY] Ale otrzymuję tylko 6 wartości.

Każdy pomysł i jak to naprawić. Bez względu na to, czy PUSTA wartość pojawia się w dowolnym miejscu, powinna znajdować się w tablicy.

Reddy
źródło

Odpowiedzi:

492

split(delimiter)domyślnie usuwa końcowe ciągi znaków z tablicy wyników. Aby wyłączyć ten mechanizm, musimy użyć przeciążonej wersji split(delimiter, limit)z limitustawioną wartością ujemną jak

String[] split = data.split("\\|", -1);

Trochę więcej szczegółów:
split(regex)wewnętrznie zwraca wynik split(regex, 0)iw dokumentacji tej metody można znaleźć (moje wyróżnienie)

Ten limitparametr kontroluje liczbę przypadków zastosowania wzorca, a zatem wpływa na długość wynikowej tablicy.

Jeśli limit njest większy od zera, wówczas wzór zostanie zastosowany co najwyżej n - 1 razy, długość tablicy nie będzie większa niż n, a ostatni wpis tablicy będzie zawierał wszystkie dane wejściowe poza ostatnim dopasowanym ogranicznikiem.

Jeśli nien jest dodatnia, wzór zostanie zastosowany tyle razy, ile to możliwe, a tablica może mieć dowolną długość.

Jeśli nwynosi zero, wówczas wzór zostanie zastosowany tyle razy, ile to możliwe, tablica może mieć dowolną długość, a końcowe ciągi znaków zostaną odrzucone .

Wyjątek :

Warto wspomnieć, że usuwanie końcowych pustych ciągów ma sens tylko wtedy, gdy takie puste ciągi są tworzone przez mechanizm podziału . Więc dla "".split(anything)ponieważ nie możemy podzielić ""dalej otrzymamy w wyniku [""]tablicy.
Dzieje się tak, ponieważ tutaj nie doszło do podziału, więc ""pomimo tego, że jest pusty i końcowy reprezentuje oryginalny ciąg, nie pusty ciąg, który został utworzony przez proces dzielenia.

jlordo
źródło
2
łał. działało doskonale. ale -1 jak to wszystko zmienia?
Reddy,
1
możesz nawet spróbowaćdata.split("\\|", 8)
Subhrajyoti Majumder
23
Nie używaj, split("\\|", 8)ponieważ ogranicza to pierwsze osiem tokenów! Jeśli ciąg znaków jest zmienny, należy go użyć, split("\\|", -1)aby tworzył nieograniczoną liczbę tokenów i nie odrzucał pustych tokenów na końcu.
ADTC
2
@Reddy -1 ( lub jakakolwiek dowolna liczba ujemna, w rzeczywistości nie ma znaczenia, jaka jest wartość bezwzględna ) mówi metodzie split, aby zachowała puste tokeny na końcu. Wartość domyślna to 0, co oznacza metodę odrzucania pustych tokenów na końcu tablicy.
ADTC
8
Najwyraźniej wiele osób spodziewało się, że zachowanie końcowych pustych ciągów jest domyślną funkcją split(regex). Wylądowali tutaj i dowiedzieli się, że tak nie jest.
Attila Tanyi,
32

Z dokumentacji String.split(String regex):

Ta metoda działa tak, jakby wywoływała metodę podziału na dwa argumenty z danym wyrażeniem i argumentem granicznym wynoszącym zero. Końcowe puste ciągi nie są zatem uwzględniane w wynikowej tablicy.

Będziesz musiał użyć wersji String.split(String regex, int limit)z dwoma argumentami o wartości ujemnej:

String[] split = data.split("\\|",-1);

Dokument:

Jeśli limit n jest większy od zera, wówczas wzór zostanie zastosowany co najwyżej n - 1 razy, długość tablicy nie będzie większa niż n, a ostatni wpis tablicy będzie zawierał wszystkie dane wejściowe poza ostatnim dopasowanym ogranicznikiem. Jeśli n jest dodatnie, wówczas wzór zostanie zastosowany tyle razy, ile to możliwe, a tablica może mieć dowolną długość. Jeśli n wynosi zero, wówczas wzór zostanie zastosowany tyle razy, ile to możliwe, tablica może mieć dowolną długość, a końcowe ciągi znaków zostaną odrzucone.

To nie pozostawi żadnych pustych elementów, w tym tych końcowych.

ppeterka
źródło
4

Z dokumentu API String.split () :

Dzieli ten ciąg wokół dopasowań podanego wyrażenia regularnego. Ta metoda działa tak, jakby wywoływała metodę podziału na dwa argumenty z danym wyrażeniem i argumentem granicznym równym zero. Końcowe puste ciągi nie są zatem uwzględniane w wynikowej tablicy.

Przeciążony String.split (regex, int) jest bardziej odpowiedni dla twojej sprawy.

PermGenError
źródło
1
To wyjaśnia zachowanie, ale nie odpowiada na pytanie.
assylias
@assylias dodał to teraz do mojej odpowiedzi :)
PermGenError 30.01.2013
4

String[] split = data.split("\\|",-1);

Nie jest to faktyczny wymóg przez cały czas. Wadę powyższego przedstawiono poniżej:

Scenerio 1:
When all data are present:
    String data = "5|6|7||8|9|10|";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 7
    System.out.println(splt.length); //output: 8

Gdy brakuje danych:

Scenerio 2: Data Missing
    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output: 8

Rzeczywistym wymaganiem jest długość powinna wynosić 7, chociaż brakuje danych. Ponieważ zdarzają się przypadki, gdy muszę wstawić do bazy danych lub czegoś innego. Możemy to osiągnąć, stosując poniższe podejście.

    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.replaceAll("\\|$","").split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output:7

To, co tutaj zrobiłem, polega na usunięciu „|” potok na końcu, a następnie dzielenie ciągu. Jeśli masz „,” jako separator, musisz dodać „, $” wewnątrz replaceAll.

Yanish Pradhananga
źródło
1

możesz mieć wiele separatorów, w tym spacje, przecinki, średniki itp. weź je w powtarzalnej grupie za pomocą [] +, na przykład:

 String[] tokens = "a , b,  ,c; ;d,      ".split( "[,; \t\n\r]+" );

będziesz miał 4 żetony - a, b, c, d

wiodące separatory w ciągu źródłowym muszą zostać usunięte przed zastosowaniem tego podziału.

jako odpowiedź na zadane pytanie:

String data = "5|6|7||8|9||";
String[] split = data.split("[\\| \t\n\r]+");

białe spacje dodane na wszelki wypadek, jeśli będziesz mieć je jako separatory wraz z |

Dmitriy Pichugin
źródło