Java String Split entfernte leere Werte

286

Ich versuche, den Wert mit einem Trennzeichen aufzuteilen. Aber ich finde die überraschenden Ergebnisse

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

Ich erwarte 8 Werte. [5,6,7, LEER, 8,9, LEER, LEER] Aber ich bekomme nur 6 Werte.

Jede Idee und wie man sie behebt. Unabhängig davon, ob der leere Wert an einem beliebigen Ort angegeben wird, sollte er sich im Array befinden.

Reddy
quelle

Antworten:

492

split(delimiter)Standardmäßig werden nachfolgende leere Zeichenfolgen aus dem Ergebnisarray entfernt. Um diesen Mechanismus deaktivieren wir überladene Version von verwenden müssen , um split(delimiter, limit)mit limitwie zu negativen Wert gesetzt

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

Wenig mehr Details:
split(regex)Gibt intern das Ergebnis von zurück split(regex, 0)und in der Dokumentation dieser Methode finden Sie (Hervorhebung von mir)

Der limitParameter steuert, wie oft das Muster angewendet wird, und wirkt sich daher auf die Länge des resultierenden Arrays aus.

Wenn die Grenze nist , größer als Null ist, dann wird das Muster höchstens n angewendet werden - 1 mal, wird das Array Länge nicht größer als n sein, und der letzte Eintrag des Arrays werden alle Eingaben über die letzte angepaßten Begrenzungszeichen enthalten.

Wenn nist nicht positiv , dann wird das Muster so oft wie möglich angewendet werden , und die Anordnung eine beliebige Länge haben kann.

Wenn nheißt Null , dann wird das Muster so oft wie möglich angewendet werden, kann das Array eine beliebige Länge haben, und leere Strings Hinter werden verworfen .

Ausnahme :

Es ist erwähnenswert, dass das Entfernen von nachgestellten leeren Zeichenfolgen nur dann sinnvoll ist , wenn solche leeren Zeichenfolgen durch einen Teilungsmechanismus erstellt wurden . Also für "".split(anything)da wir nicht teilen können ""weiter werden wir als Ergebnis erhalten [""]Array.
Dies geschieht, weil hier keine Aufteilung stattgefunden hat. ""Obwohl dies leer ist und das Nachlaufen die ursprüngliche Zeichenfolge darstellt, handelt es sich nicht um eine leere Zeichenfolge, die durch den Aufteilungsprozess erstellt wurde.

jlordo
quelle
2
Beeindruckend. das hat hervorragend funktioniert. aber -1 wie ändert das alles?
Reddy
1
Sie können es sogar mitdata.split("\\|", 8)
Subhrajyoti Majumder
23
Nicht verwenden, split("\\|", 8)da dies auf die ersten acht Token beschränkt ist! Wenn Ihre Zeichenfolge variabel ist, sollten Sie sie verwenden split("\\|", -1), damit eine unbegrenzte Anzahl von Token erstellt wird und am Ende keine leeren Token verworfen werden.
ADTC
2
@Reddy -1 ( oder eine negative Zahl, es spielt keine Rolle, wie hoch der absolute Wert ist ) weist die Split-Methode an, die leeren Token am Ende beizubehalten . Der Standardwert ist 0, wodurch die Methode angewiesen wird, leere Token am Ende des Arrays zu verwerfen.
ADTC
8
Anscheinend haben viele Leute erwartet, dass das Beibehalten der nachfolgenden leeren Zeichenfolgen die Standardfunktionalität für ist split(regex). Sie sind hier gelandet und haben herausgefunden, dass es nicht so ist.
Attila Tanyi
32

Aus der Dokumentation von String.split(String regex):

Diese Methode funktioniert so, als würde die Split-Methode mit zwei Argumenten mit dem angegebenen Ausdruck und einem Grenzargument von Null aufgerufen. Nachfolgende leere Zeichenfolgen sind daher nicht im resultierenden Array enthalten.

Sie müssen also die Version String.split(String regex, int limit)mit zwei Argumenten mit einem negativen Wert verwenden:

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

Doc:

Wenn der Grenzwert n größer als Null ist, wird das Muster höchstens n - 1 Mal angewendet, die Länge des Arrays ist nicht größer als n, und der letzte Eintrag des Arrays enthält alle Eingaben über das zuletzt übereinstimmende Trennzeichen hinaus. Wenn n nicht positiv ist, wird das Muster so oft wie möglich angewendet und das Array kann eine beliebige Länge haben. Wenn n Null ist, wird das Muster so oft wie möglich angewendet, das Array kann eine beliebige Länge haben und nachfolgende leere Zeichenfolgen werden verworfen.

Dadurch werden keine leeren Elemente ausgelassen, einschließlich der nachfolgenden.

ppeterka
quelle
4

Aus dem String.split () API-Dokument :

Teilt diese Zeichenfolge um Übereinstimmungen des angegebenen regulären Ausdrucks. Diese Methode funktioniert so, als würde die Split-Methode mit zwei Argumenten mit dem angegebenen Ausdruck und einem Grenzargument von Null aufgerufen. Nachfolgende leere Zeichenfolgen sind daher nicht im resultierenden Array enthalten.

Überladene String.split (Regex, Int) ist für Ihren Fall besser geeignet.

PermGenError
quelle
1
Das erklärt das Verhalten, beantwortet aber die Frage nicht.
Assylias
@assylias hat es jetzt zu meiner Antwort hinzugefügt :)
PermGenError
4

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

Dies ist nicht immer die eigentliche Anforderung. Der Nachteil von oben ist unten gezeigt:

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

Wenn Daten fehlen:

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

Die tatsächliche Anforderung ist, dass die Länge 7 betragen sollte, obwohl Daten fehlen. Weil es Fälle gibt, in denen ich in eine Datenbank oder etwas anderes einfügen muss. Wir können dies erreichen, indem wir den folgenden Ansatz verwenden.

    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

Was ich hier getan habe ist, ich entferne "|" Rohr am Ende und dann den String teilen. Wenn Sie "," als Trennzeichen haben, müssen Sie ", $" in replaceAll hinzufügen.

Yanish Pradhananga
quelle
1

Möglicherweise haben Sie mehrere Trennzeichen, einschließlich Leerzeichen, Kommas, Semikolons usw. Nehmen Sie diese in wiederholbaren Gruppen mit [] +, wie z.

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

Sie haben 4 Token - a, b, c, d

Führende Trennzeichen in der Quellzeichenfolge müssen entfernt werden, bevor diese Aufteilung angewendet wird.

als Antwort auf die gestellte Frage:

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

Leerzeichen für alle Fälle hinzugefügt, wenn Sie diese als Trennzeichen zusammen mit | haben

Dmitriy Pichugin
quelle