Estoy construyendo un comparador que proporciona la capacidad de clasificación de varias columnas en una cadena delimitada. Actualmente estoy usando el método de división de la clase String como mi opción preferida para dividir la cadena sin procesar en tokens.
¿Es esta la mejor manera de convertir la cadena sin procesar en una matriz de cadenas? Ordenaré millones de filas, así que creo que el enfoque es importante.
Parece funcionar bien y es muy fácil, pero no estoy seguro si hay una forma más rápida en Java.
Así es como funciona el tipo en mi Comparador:
public int compare(String a, String b) {
String[] aValues = a.split(_delimiter, _columnComparators.length);
String[] bValues = b.split(_delimiter, _columnComparators.length);
int result = 0;
for( int index : _sortColumnIndices ) {
result = _columnComparators[index].compare(aValues[index], bValues[index]);
if(result != 0){
break;
}
}
return result;
}
Después de comparar los diversos enfoques, lo creas o no, el método de división fue el más rápido con la última versión de Java. Puede descargar mi comparador completo aquí: https://sourceforge.net/projects/multicolumnrowcomparator/
fuente
StringUtils.split[PreserveAllTokens](text, delimiter)
.Respuestas:
He escrito una prueba de referencia rápida y sucia para esto. Compara 7 métodos diferentes, algunos de los cuales requieren un conocimiento específico de los datos que se dividen.
Para la división básica de propósito general, Guava Splitter es 3.5 veces más rápido que String # split () y recomendaría usar eso. Stringtokenizer es un poco más rápido que eso y dividirse con indexOf es dos veces más rápido que otra vez.
Para ver el código y más información, visite http://demeranville.com/battle-of-the-tokenizers-delimited-text-parser-performance/
fuente
Como escribe @Tom, un enfoque de tipo indexOf es más rápido que
String.split()
, ya que este último trata con expresiones regulares y tiene una sobrecarga adicional para ellos.Sin embargo, un cambio de algoritmo que podría darte una súper velocidad. Suponiendo que este comparador se vaya a utilizar para ordenar sus ~ 100,000 cadenas, no escriba el
Comparator<String>
. Porque, en el curso de su clasificación, la misma cadena probablemente se comparará varias veces, por lo que la dividirá varias veces, etc.Divida todas las Cadenas una vez en Cadenas [] s, y
Comparator<String[]>
ordene la Cadena []. Luego, al final, puedes combinarlos todos juntos.Alternativamente, también podría usar un Mapa para almacenar en caché la Cadena -> Cadena [] o viceversa. por ejemplo (incompleto) También tenga en cuenta que está intercambiando memoria por velocidad, espero que tenga mucha RAM
fuente
sortAndSave()
llamada, entonces no debería quedarse sin memoria debido a una gran caché. En mi opinión, el código debe tener algunos ganchos adicionales, como disparar eventos o llamar a métodos protegidos de no hacer nada que los usuarios como usted podrían anular. (Además, no deberían ser todos los métodos estáticos para que puedan hacer esto) Es posible que desee ponerse en contacto con los autores y presentar una solicitud.De acuerdo con estos puntos de referencia , StringTokenizer es más rápido para dividir cadenas, pero no devuelve una matriz que lo hace menos conveniente.
Si necesita ordenar millones de filas, le recomiendo usar un RDBMS.
fuente
Este es el método que uso para analizar archivos delimitados por tabulaciones grandes (1GB +). Tiene mucho menos gastos generales que
String.split()
, pero se limita achar
delimitador. Si alguien tiene un método más rápido, me gustaría verlo. Esto también se puede hacer de nuevoCharSequence
yCharSequence.subSequence
, pero eso requiere implementaciónCharSequence.indexOf(char)
(consulte el método del paqueteString.indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex)
si está interesado).fuente