Le fractionnement de la chaîne Java a supprimé les valeurs vides

286

J'essaie de diviser la valeur à l'aide d'un séparateur. Mais je trouve les résultats surprenants

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

Je m'attends à obtenir 8 valeurs. [5,6,7, VIDE, 8,9, VIDE, VIDE] Mais je ne reçois que 6 valeurs.

Toute idée et comment y remédier. Quelle que soit la valeur EMPTY, elle doit se trouver dans un tableau.

Reddy
la source

Réponses:

492

split(delimiter)par défaut, supprime les chaînes vides de fin du tableau de résultats. Pour désactiver ce mécanisme, nous devons utiliser une version surchargée de split(delimiter, limit)avec limitune valeur négative comme

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

Un peu plus de détails:
split(regex)retourne en interne le résultat de split(regex, 0)et dans la documentation de cette méthode que vous pouvez trouver (soulignement le mien)

Le limitparamètre contrôle le nombre de fois que le motif est appliqué et affecte donc la longueur du tableau résultant.

Si la limite nest supérieure à zéro, le modèle sera appliqué au plus n - 1 fois, la longueur du tableau ne sera pas supérieure à n et la dernière entrée du tableau contiendra toutes les entrées au-delà du dernier délimiteur correspondant.

Si elle nn'est pas positive, le motif sera appliqué autant de fois que possible et le tableau peut avoir n'importe quelle longueur.

Si nest égal à zéro, le modèle sera appliqué autant de fois que possible, le tableau peut avoir n'importe quelle longueur et les chaînes vides de fin seront supprimées .

Exception :

Il convient de mentionner que la suppression d'une chaîne vide de fin n'a de sens que si ces chaînes vides sont créées par un mécanisme de fractionnement . Donc, "".split(anything)puisque nous ne pouvons pas diviser ""plus loin, nous obtiendrons un [""]tableau de résultats .
Cela se produit parce que le fractionnement ne s'est pas produit ici, donc ""bien qu'il soit vide et que la fin représente la chaîne d' origine , pas une chaîne vide créée par le processus de fractionnement.

jlordo
la source
2
sensationnel. cela a fonctionné avec brio. mais -1 comment cela change tout?
Reddy
1
vous pouvez même essayer avecdata.split("\\|", 8)
Subhrajyoti Majumder
23
Ne l'utilisez pas split("\\|", 8)car cela limite les huit premiers jetons! Si votre chaîne est variable, vous devez l'utiliser split("\\|", -1)pour créer un nombre illimité de jetons et ne pas éliminer les jetons vides à la fin.
ADTC
2
@Reddy -1 ( ou tout nombre négatif en fait, peu importe la valeur absolue ) indique à la méthode de partage de conserver les jetons vides à la fin. La valeur par défaut est 0, ce qui indique à la méthode de supprimer les jetons vides à la fin du tableau.
ADTC
8
Apparemment, beaucoup de gens s'attendaient à ce que conserver les chaînes vides de fin soit la fonctionnalité par défaut de split(regex). Ils se sont retrouvés ici et ont découvert que ce n'était pas le cas.
Attila Tanyi
32

À partir de la documentation de String.split(String regex):

Cette méthode fonctionne comme si en appelant la méthode de fractionnement à deux arguments avec l'expression donnée et un argument limite de zéro. Les chaînes vides de fin ne sont donc pas incluses dans le tableau résultant.

Vous devrez donc utiliser la version String.split(String regex, int limit)à deux arguments avec une valeur négative:

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

Doc:

Si la limite n est supérieure à zéro, le modèle sera appliqué au plus n - 1 fois, la longueur du tableau ne sera pas supérieure à n et la dernière entrée du tableau contiendra toutes les entrées au-delà du dernier délimiteur correspondant. Si n n'est pas positif, le motif sera appliqué autant de fois que possible et le tableau peut avoir n'importe quelle longueur. Si n est zéro, le motif sera appliqué autant de fois que possible, le tableau peut avoir n'importe quelle longueur et les chaînes vides de fin seront rejetées.

Cela ne laissera pas de côté les éléments vides, y compris les éléments de fin.

ppeterka
la source
4

Du String.split () API Doc :

Fractionne cette chaîne autour des correspondances de l'expression régulière donnée. Cette méthode fonctionne comme si en appelant la méthode de fractionnement à deux arguments avec l'expression donnée et un argument limite de zéro. Les chaînes vides de fin ne sont donc pas incluses dans le tableau résultant.

Un String.split surchargé (regex, int) est plus approprié pour votre cas.

PermGenError
la source
1
Cela explique le comportement mais ne répond pas à la question.
assylias
@assylias l'a ajouté à ma réponse maintenant :)
PermGenError
4

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

Ce n'est pas l'exigence réelle en tout temps. L'inconvénient de ci-dessus est indiqué ci-dessous:

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

Lorsque des données sont manquantes:

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

La véritable exigence est que la longueur devrait être de 7 bien qu'il manque des données. Parce qu'il y a des cas comme quand j'ai besoin d'insérer dans la base de données ou autre chose. Nous pouvons y parvenir en utilisant l'approche ci-dessous.

    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

Ce que j'ai fait ici, c'est que je supprime "|" tuyau à la fin, puis diviser la chaîne. Si vous avez "," comme séparateur, vous devez ajouter ", $" à l'intérieur de replaceAll.

Yanish Pradhananga
la source
1

vous pouvez avoir plusieurs séparateurs, y compris des espaces, des virgules, des points-virgules, etc. prenez ceux du groupe répétable avec [] +, comme:

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

vous aurez 4 jetons - a, b, c, d

les séparateurs de tête de la chaîne source doivent être supprimés avant d'appliquer ce fractionnement.

comme réponse à la question posée:

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

espaces blancs ajoutés juste au cas où si vous les avez comme séparateurs avec |

Dmitriy Pichugin
la source