Estou construindo um comparador que fornece capacidade de classificação de várias colunas em uma String delimitada. Atualmente, estou usando o método split da classe String como minha escolha preferida para dividir a String bruta em tokens.
Essa é a melhor maneira de converter a String bruta em uma matriz String? Vou classificar milhões de linhas, então acho que a abordagem é importante.
Parece funcionar bem e é muito fácil, mas não tenho certeza se existe uma maneira mais rápida em java.
Aqui está como a classificação funciona no meu 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;
}
Depois de comparar as várias abordagens, acredite ou não, o método split foi o mais rápido usando a versão mais recente do java. Você pode fazer o download do meu comparador completo aqui: https://sourceforge.net/projects/multicolumnrowcomparator/
fonte
StringUtils.split[PreserveAllTokens](text, delimiter)
.Respostas:
Eu escrevi um teste de benchmark rápido e sujo para isso. Ele compara 7 métodos diferentes, alguns dos quais requerem conhecimento específico dos dados que estão sendo divididos.
Para a divisão básica de uso geral, o Guava Splitter é 3,5x mais rápido que o String # split () e eu recomendo usá-lo. O stringtokenizer é um pouco mais rápido que isso e dividir-se com indexOf é duas vezes mais rápido do que isso.
Para obter o código e mais informações, consulte http://demeranville.com/battle-of-the-tokenizers-delimited-text-parser-performance/
fonte
Como o @Tom escreve, uma abordagem do tipo indexOf é mais rápida que
String.split()
, uma vez que a última lida com expressões regulares e possui uma sobrecarga extra para elas.No entanto, uma alteração no algoritmo pode fornecer uma super aceleração. Supondo que este comparador seja usado para classificar suas ~ 100.000 Strings, não escreva o
Comparator<String>
. Porque, no decorrer da sua classificação, a mesma String provavelmente será comparada várias vezes, então você a dividirá várias vezes, etc ...Divida todas as Strings uma vez em String [] s e
Comparator<String[]>
classifique a String []. Então, no final, você pode combiná-los todos juntos.Como alternativa, você também pode usar um mapa para armazenar em cache a String -> String [] ou vice-versa. Por exemplo, (esboçado) Observe também que você está trocando memória por velocidade, espero ter muita RAM
fonte
sortAndSave()
chamada, não deve ficar sem memória devido a um cache enorme. Na IMO, o código deve ter alguns ganchos extras, como disparar eventos ou chamar métodos protegidos do nada, que usuários como você podem substituir. (Além disso, não devem ser todos os métodos estáticos para que eles possam fazer isso). Você pode entrar em contato com os autores e registrar uma solicitação.De acordo com esses benchmarks , o StringTokenizer é mais rápido para dividir strings, mas não retorna uma matriz, o que o torna menos conveniente.
Se você precisar classificar milhões de linhas, recomendo usar um RDBMS.
fonte
Esse é o método que eu uso para analisar arquivos grandes (1GB +) delimitados por tabulação. Tem muito menos sobrecarga do que
String.split()
, mas é limitado achar
um delimitador. Se alguém tiver um método mais rápido, eu gostaria de vê-lo. Isso também pode ser feito repetidamenteCharSequence
eCharSequence.subSequence
, mas isso requer implementaçãoCharSequence.indexOf(char)
(consulte o método do pacote,String.indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex)
se estiver interessado).fonte