A divisão de Java String removeu valores vazios

286

Estou tentando dividir o valor usando um separador. Mas estou encontrando resultados surpreendentes

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

Espero obter 8 valores. [5,6,7, VAZIO, 8,9, VAZIO, VAZIO] Mas estou recebendo apenas 6 valores.

Alguma idéia e como consertar. Não importa o valor vazio que esteja em qualquer lugar, ele deve estar na matriz.

Reddy
fonte

Respostas:

492

split(delimiter)por padrão, remove seqüências de caracteres vazias à direita da matriz de resultados. Para desativar esse mecanismo, precisamos usar a versão sobrecarregada de split(delimiter, limit)com limitvalor negativo como

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

Um pouco mais de detalhes:
split(regex)retorna internamente o resultado de split(regex, 0)e na documentação deste método você encontra (ênfase minha)

O limitparâmetro controla o número de vezes que o padrão é aplicado e, portanto, afeta o comprimento da matriz resultante.

Se o limite nfor maior que zero , o padrão será aplicado no máximo n - 1 vezes, o comprimento da matriz não será maior que n e a última entrada da matriz conterá toda a entrada além do último delimitador correspondente.

Se nãon for positivo , o padrão será aplicado quantas vezes for possível e a matriz pode ter qualquer comprimento.

Se nfor zero , o padrão será aplicado quantas vezes for possível, a matriz pode ter qualquer comprimento e as seqüências vazias à direita serão descartadas .

Exceção :

Vale ressaltar que remover a seqüência vazia à direita faz sentido se essas seqüências vazias forem criadas pelo mecanismo de divisão . Então, "".split(anything)como não podemos dividir ""mais, obteremos como [""]matriz de resultados .
Isso acontece porque a divisão não aconteceu aqui, portanto, ""apesar de estar vazio e à direita, representa a sequência original , não a sequência vazia que foi criada pelo processo de divisão.

jlordo
fonte
2
Uau. isso funcionou brilhantemente. mas -1 como isso muda tudo?
Reddy
1
você pode até tentar comdata.split("\\|", 8)
Subhrajyoti Majumder
23
Não use, split("\\|", 8)pois isso limita os oito primeiros tokens! Se sua string for variável, você deve usá split("\\|", -1)-la para criar um número ilimitado de tokens e não descartar tokens vazios no final.
ADTC
2
@Reddy -1 ( ou qualquer número negativo, de fato, não importa qual é o valor absoluto ) diz ao método split para manter os tokens vazios no final. O padrão é 0, que informa ao método para descartar tokens vazios no final da matriz.
ADTC
8
Aparentemente, muitas pessoas esperavam que manter as seqüências vazias à direita fosse a funcionalidade padrão split(regex). Eles acabaram aqui e descobriram que não é.
Attila Tanyi
32

A partir da documentação de String.split(String regex):

Esse método funciona como se invocando o método de divisão de dois argumentos com a expressão fornecida e um argumento de limite igual a zero. As seqüências de caracteres vazias à direita, portanto, não são incluídas na matriz resultante.

Portanto, você terá que usar a versão de dois argumentos String.split(String regex, int limit)com um valor negativo:

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

Doc:

Se o limite n for maior que zero, o padrão será aplicado no máximo n - 1 vezes, o comprimento da matriz não será maior que n e a última entrada da matriz conterá toda a entrada além do último delimitador correspondente. Se n for não positivo, o padrão será aplicado tantas vezes quanto possível e a matriz poderá ter qualquer comprimento. Se n for zero, o padrão será aplicado quantas vezes for possível, a matriz pode ter qualquer comprimento e as seqüências vazias à direita serão descartadas.

Isso não deixará de fora nenhum elemento vazio, incluindo os à direita.

ppeterka
fonte
4

No documento da API String.split () :

Divide essa string em torno das correspondências da expressão regular especificada. Esse método funciona como se invocando o método de divisão de dois argumentos com a expressão fornecida e um argumento de limite igual a zero. As seqüências de caracteres vazias à direita, portanto, não são incluídas na matriz resultante.

Sobrecarregado String.split (regex, int) é mais apropriado para o seu caso.

PermGenError
fonte
1
Isso explica o comportamento, mas não responde à pergunta.
assylias
@assylias adicionou-o à minha resposta agora :)
PermGenError 30/01
4

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

Esse não é o requisito real o tempo todo. A desvantagem acima é mostrada abaixo:

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

Quando faltam dados:

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

O requisito real é que o comprimento deve ser 7, embora haja dados ausentes. Porque há casos como quando eu preciso inserir no banco de dados ou algo mais. Podemos conseguir isso usando a abordagem abaixo.

    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

O que eu fiz aqui é que estou removendo "|" no final e depois dividindo a String. Se você tiver "," como separador, precisará adicionar ", $" dentro de replaceAll.

Yanish Pradhananga
fonte
1

você pode ter vários separadores, incluindo caracteres de espaço em branco, vírgulas, ponto e vírgula etc.

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

você terá 4 fichas - a, b, c, d

separadores principais na cadeia de origem precisam ser removidos antes de aplicar essa divisão.

como resposta à pergunta:

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

espaços em branco adicionados apenas no caso, se você os tiver como separadores junto com |

Dmitriy Pichugin
fonte