Son esencialmente caballos para cursos.
Scanner
está diseñado para casos en los que necesita analizar una cadena, extrayendo datos de diferentes tipos. Es muy flexible, pero podría decirse que no le brinda la API más simple para simplemente obtener una matriz de cadenas delimitadas por una expresión particular.
String.split()
y Pattern.split()
darle una sintaxis fácil para hacer esto último, pero eso es esencialmente todo lo que hacen. Si desea analizar las cadenas resultantes o cambiar el delimitador a mitad de camino según un token en particular, no lo ayudarán con eso.
StringTokenizer
es aún más restrictivo que String.split()
, y también un poco más complicado de usar. Está esencialmente diseñado para extraer tokens delimitados por subcadenas fijas. Debido a esta restricción, es aproximadamente el doble de rápido que String.split()
. (Consulte mi comparación de String.split()
yStringTokenizer
.) También es anterior a la API de expresiones regulares, de la cual String.split()
forma parte.
Notarás por mis tiempos que String.split()
aún pueden tokenizar miles de cadenas en unos pocos milisegundos en una máquina típica. Además, tiene la ventaja de StringTokenizer
que le proporciona la salida como una matriz de cadenas, que generalmente es lo que desea. Usar un Enumeration
, según lo provisto StringTokenizer
, es demasiado "sintácticamente exigente" la mayor parte del tiempo. Desde este punto de vista, StringTokenizer
es un poco una pérdida de espacio hoy en día, y también puede usarlo String.split()
.
StringTokenizer
mi mejor opción porqueString.split()
simplemente se quedará sin memoria?Comencemos por eliminar
StringTokenizer
. Se está haciendo viejo y ni siquiera admite expresiones regulares. Su documentación establece:Así que vamos a tirarlo de inmediato. Eso se va
split()
yScanner
. ¿Cual es la diferencia entre ellos?Por un lado,
split()
simplemente devuelve una matriz, lo que facilita el uso de un bucle foreach:Scanner
se construye más como una secuencia:o
(Tiene una API bastante grande , así que no pienses que siempre está restringido a cosas tan simples).
Esta interfaz de estilo de transmisión puede ser útil para analizar archivos de texto simples o entradas de consola, cuando no tiene (o no puede obtener) toda la entrada antes de comenzar a analizar.
Personalmente, el único momento que recuerdo haber usado
Scanner
es para proyectos escolares, cuando tuve que obtener la entrada del usuario desde la línea de comandos. Hace que este tipo de operación sea fácil. Pero si tengo una con laString
que quiero separarme, es casi una obviedadsplit()
.fuente
Scanner
detectar nuevos caracteres de línea en un determinadoString
. Dado que los nuevos caracteres de línea pueden variar de una plataforma a otra (¡mirePattern
el javadoc!) Y NO se garantiza que la cadena de entrada se ajusteSystem.lineSeparator()
, creo que esScanner
más adecuado ya que ya sabe qué nuevos caracteres de línea debe buscar al llamarnextLine()
. ParaString.split
que tendrá que alimentar en el patrón de expresión correcta para detectar separadores de línea, que no encuentro almacenados en cualquier posición estándar (lo mejor que puedo hacer es copiar desde laScanner
fuente de la clase).StringTokenizer siempre estuvo ahí. Es el más rápido de todos, pero el lenguaje de enumeración puede no parecer tan elegante como los demás.
split surgió en JDK 1.4. Más lento que el tokenizador pero más fácil de usar, ya que se puede llamar desde la clase String.
El escáner llegó a estar en JDK 1.5. Es el más flexible y llena un vacío de larga data en la API de Java para admitir un equivalente de la famosa familia de funciones Cs scanf.
fuente
Si tiene un objeto String que desea tokenizar, favorezca el uso del método de división de String sobre un StringTokenizer. Si está analizando datos de texto desde una fuente externa a su programa, como desde un archivo o desde el usuario, ahí es muy útil un escáner.
fuente
La división es lenta, pero no tan lenta como el escáner. StringTokenizer es más rápido que dividir. Sin embargo, descubrí que podía obtener el doble de velocidad, intercambiando cierta flexibilidad, para obtener un aumento de velocidad, lo que hice en JFastParser https://github.com/hughperkins/jfastparser
Prueba en una cadena que contiene un millón de dobles:
fuente
String.split parece ser mucho más lento que StringTokenizer. La única ventaja de dividir es que obtienes una variedad de tokens. También puede usar cualquier expresión regular en división. org.apache.commons.lang.StringUtils tiene un método dividido que funciona mucho más rápido que cualquiera de los dos a saber. StringTokenizer o String.split. Pero la utilización de la CPU para los tres es casi la misma. Por lo tanto, también necesitamos un método que requiera menos CPU, que todavía no puedo encontrar.
fuente
Recientemente realicé algunos experimentos sobre el mal rendimiento de String.split () en situaciones muy sensibles al rendimiento. Puede encontrar esto útil.
http://eblog.chrononsystems.com/hidden-evils-of-javas-stringsplit-and-stringr
La esencia es que String.split () compila un patrón de Expresión Regular cada vez y, por lo tanto, puede ralentizar su programa, en comparación con si usa un objeto Patrón precompilado y lo usa directamente para operar en una Cadena.
fuente
Para los escenarios predeterminados, sugeriría Pattern.split () también, pero si necesita un rendimiento máximo (especialmente en Android, todas las soluciones que probé son bastante lentas) y solo necesita dividir por un solo carácter, ahora uso mi propio método:
Use "abc" .toCharArray () para obtener la matriz de caracteres para una Cadena. Por ejemplo:
fuente
Una diferencia importante es que String.split () y Scanner pueden producir cadenas vacías, pero StringTokenizer nunca lo hace.
Por ejemplo:
Salida:
Esto se debe a que el delimitador para String.split () y Scanner.useDelimiter () no es solo una cadena, sino una expresión regular. Podemos reemplazar el delimitador "" con "+" en el ejemplo anterior para que se comporten como StringTokenizer.
fuente
String.split () funciona muy bien pero tiene sus propios límites, como si quisiera dividir una cadena como se muestra a continuación en función del símbolo de tubería simple o doble (|), no funciona. En esta situación, puede usar StringTokenizer.
ABC | IJK
fuente