Eles são essencialmente cavalos para percursos.
Scanner
foi desenvolvido para casos em que você precisa analisar uma string, obtendo dados de diferentes tipos. É muito flexível, mas sem dúvida não fornece a API mais simples para simplesmente obter uma matriz de seqüências delimitadas por uma expressão específica.
String.split()
e Pattern.split()
fornecer uma sintaxe fácil para você fazer o último, mas isso é basicamente tudo o que eles fazem. Se você deseja analisar as seqüências de caracteres resultantes ou alterar o delimitador no meio, dependendo de um token específico, eles não o ajudarão nisso.
StringTokenizer
é ainda mais restritivo do que String.split()
e também um pouco mais difícil de usar. Ele foi projetado essencialmente para extrair tokens delimitados por substrings fixos. Por causa dessa restrição, é duas vezes mais rápido que String.split()
. (Veja minha comparação de String.split()
eStringTokenizer
.) Ele também antecede a API de expressões regulares, da qual String.split()
faz parte.
Você notará pelos meus tempos que String.split()
ainda podem tokenizar milhares de strings em alguns milissegundos em uma máquina típica. Além disso, tem a vantagem de StringTokenizer
fornecer a saída como uma matriz de strings, que geralmente é o que você deseja. Usar um Enumeration
, como fornecido por StringTokenizer
, é muito "sintaticamente exigente" na maioria das vezes. Deste ponto de vista, StringTokenizer
é um pouco de desperdício de espaço hoje em dia, e você também pode usar String.split()
.
StringTokenizer
ainda não é minha melhor aposta, porqueString.split()
simplesmente ficará sem memória?Vamos começar eliminando
StringTokenizer
. Está ficando velho e nem suporta expressões regulares. Sua documentação declara:Então, vamos jogar fora imediatamente. Isso sai
split()
eScanner
. Qual a diferença entre eles?Por um lado,
split()
simplesmente retorna uma matriz, o que facilita o uso de um loop foreach:Scanner
é construído mais como um fluxo:ou
(Ele possui uma API bastante grande , não pense que ela está sempre restrita a coisas tão simples.)
Essa interface no estilo de fluxo pode ser útil para analisar arquivos de texto simples ou entrada do console, quando você não possui (ou não pode obter) toda a entrada antes de começar a analisar.
Pessoalmente, a única vez em que me lembro de usar
Scanner
é em projetos escolares, quando tive que obter informações do usuário na linha de comando. Isso facilita esse tipo de operação. Mas se eu tiver umString
que eu quero dividir, é quase um acéfalo para acompanharsplit()
.fonte
Scanner
detectar novos caracteres de linha em um dadoString
. Como os novos caracteres de linha podem variar de plataforma para plataforma (vejaPattern
o javadoc!) E a sequência de entrada NÃO é garantidaSystem.lineSeparator()
, eu achoScanner
mais adequado, pois ele já sabe quais novos caracteres de linha procurar ao chamarnextLine()
. PoisString.split
terei que alimentar o padrão de regex correto para detectar os separadores de linha, que não encontro armazenados em nenhum local padrão (o melhor que posso fazer é copiá-lo daScanner
fonte da classe).O StringTokenizer estava sempre lá. É o mais rápido de todos, mas o idioma do tipo enumeração pode não parecer tão elegante quanto os outros.
a divisão surgiu no JDK 1.4. Mais lento que o tokenizer, mas mais fácil de usar, pois é possível chamar da classe String.
O scanner chegou ao JDK 1.5. É o mais flexível e preenche uma lacuna de longa data na API Java para suportar um equivalente da famosa família de funções Cs scanf.
fonte
Se você tiver um objeto String que deseja tokenizar, use o método split da String em vez de um StringTokenizer. Se você estiver analisando dados de texto de uma fonte externa ao seu programa, como de um arquivo ou do usuário, é aí que um Scanner é útil.
fonte
A divisão é lenta, mas não tão lenta quanto o Scanner. O StringTokenizer é mais rápido que o split. No entanto, descobri que poderia obter o dobro da velocidade, trocando alguma flexibilidade, para obter um aumento de velocidade, o que fiz no JFastParser https://github.com/hughperkins/jfastparser
Teste em uma string contendo um milhão de vezes:
fonte
String.split parece ser muito mais lento que StringTokenizer. A única vantagem da divisão é que você obtém uma matriz de tokens. Além disso, você pode usar qualquer expressão regular em divisão. org.apache.commons.lang.StringUtils possui um método de divisão que funciona muito mais rápido do que qualquer um dos dois viz. StringTokenizer ou String.split. Mas a utilização da CPU para todos os três é quase a mesma. Por isso, também precisamos de um método que consome menos CPU, que ainda não consigo encontrar.
fonte
Recentemente, fiz alguns experimentos sobre o mau desempenho de String.split () em situações altamente sensíveis ao desempenho. Você pode achar isso útil.
http://eblog.chrononsystems.com/hidden-evils-of-javas-stringsplit-and-stringr
A essência é que String.split () compila um padrão de Expressão Regular a cada vez e, portanto, pode tornar seu programa mais lento, comparado a se você usar um objeto Pattern pré-compilado e usá-lo diretamente para operar em uma String.
fonte
Para os cenários padrão, eu sugeriria Pattern.split () também, mas se você precisar de desempenho máximo (especialmente no Android, todas as soluções que testei são bastante lentas) e você só precisará dividir por um único caractere, agora uso meu próprio método:
Use "abc" .toCharArray () para obter a matriz char para uma String. Por exemplo:
fonte
Uma diferença importante é que o String.split () e o Scanner podem produzir cadeias vazias, mas o StringTokenizer nunca o faz.
Por exemplo:
Resultado:
Isso ocorre porque o delimitador para String.split () e Scanner.useDelimiter () não é apenas uma sequência, mas uma expressão regular. Podemos substituir o delimitador "" por "+" no exemplo acima para fazê-lo se comportar como StringTokenizer.
fonte
String.split () funciona muito bem, mas possui seus próprios limites, como se você quisesse dividir uma string como mostrado abaixo com base no símbolo de barra simples ou dupla (|), ela não funciona. Nessa situação, você pode usar o StringTokenizer.
ABC | IJK
fonte