Usando a classe string tokenizer para eliminar espacos desnecessarios de um registo

10 respostas
M

Ola pessoal, tenho um pequeno sistema de registo de estudantes em Java, com banco de dados mysql, queria que me ajudassem a solucionar o seguinte problema. Na digitacao de dados, os nomes dos estudantes foram mal digitados, isto porque, possivelmente o operador usou o tabulador e nao controlou os espacos. O que ta a acontecer é que muitas vezes quando tento pesquisar um registo usando o LIKE, nos casos em que existe esse erro, ele nao encontra o registro. Sao situacoes do tipo:

mario david matsinhe
  • ele encontra este nome porque nao tem o referido problema

casos como:

mario david matsinhe

mario    david matsinhe

mario david   matsinhe

nao sao reconhecidos. gostaria que me ajudassem, atraves duma query ou dum algoritmo a detectar e resolver estas situacoes. O banco de dados ta com cerca de 15000 registos. To a pensar em usar a classe String tokenizer (para eliminar os espacos), mas nao domino. Peco que me deem uma orientacao

10 Respostas

J

Seria algo assim:

// nesse exemplo usamos o ponto como separador
String semPontos;
StringTokenizer aux = new StringTokenizer(args[i], ".");
				while(aux.hasMoreTokens()){
					semPontos += aux.nextToken();					
				}

Espero ter ajudado…

T

É recomendável pegar um tempinho e escrever um programa que normalize os nomes no seu banco de dados, para que você não tenha mais esse problema.
Por exemplo, deixe os nomes todos em maiúsculas, e com apenas um espaço entre cada palavra.
Dica: prefira não usar StringTokenizer; é uma classe muito antiga e difícil de usar - e a própria documentação indica para não usá-la em novos projetos. (Só que os livros didáticos ainda continuam a ensiná-la, provavelmente porque os professores nunca atualizaram seus livros :frowning: )

class NormalizarNome {
    /**
    * Normaliza os nomes (mas não remove os acentos).
    * Nós apenas passamos os nomes para maiúsculas e 
    * removemos os espaços e tabulações excedentes.
    * Pode-se modificar esta rotina para implementar
    * melhores normalizações (por exemplo, remover
    * caracteres especiais e tirar os acentos das palavras.)
    * @param nome O nome a ser normalizado.
    * @return O nome normalizado. 
    */
    public static String normaliza (String nome) {
        String ret;
        // Passar o nome para maiúsculas
        ret = nome.toUpperCase();
        // Trocar os espaços duplicados, tabulações etc. por um espaço
        ret = ret.replaceAll ("\\s+", " ");
        // Remover o espaço no início
        ret = ret.replaceAll ("^\\s+", "");
        // Remover o espaço no fim
        ret = ret.replaceAll ("\\s+$", "");
        return ret;
    }
    /**
    * Exemplo de uso.
    */
    public static void main(String[] args) {
        String[] teste = {
"\tmario david matsinhe",
"    mario   david \tmatsinhe",
"mario david matsinhe        ",
"mario david matsinhe"
        };
        for (int i = 0; i &lt teste.length; ++i) {
                System.out.println ("[" + normaliza (teste[i]) + "]");
        }
    }
}
H
package string;

import java.util.StringTokenizer;

class ValidandoString 
{
    public static void main(String[] args) 
    {
        String texto = "Texto  a   ser    Corrigido.";
        
        StringBuffer textoCorrigido = new StringBuffer();
        
        StringTokenizer token = new StringTokenizer(texto, " ");
        while(token.hasMoreTokens()) 
        {
            textoCorrigido.append(token.nextToken() + " ");
        }
        System.out.println(textoCorrigido);
    }
}
R

mt bom, mesmo sendo um topico antigo me ajudo bastante :slight_smile:

S

Me ajudou tb , obrigado

V

Só tem um detalhe. Desde o Java 5, o StringTokenizer deve ser substituído pelo método split.
E a classe StringBuilder deve substituir a classe StringBuffer.

O código do Hugo Pinho, hoje em dia, fica assim:

package string;

import java.util.StringTokenizer;

class ValidandoString {
    public static void main(String[] args) {
        String texto = "Texto  a   ser    Corrigido.";
        StringBuilder textoCorrigido = new StringBuilder();

        for (String palavra : texto.split(" ")) {
            textoCorrigido.append(palavra).append(" ");
        }
        System.out.println(textoCorrigido);  
    }
}

Por isso é bom tomar cuidado ao copiar de tópicos velhos. ;)

D

"Só tem um detalhe. Desde o Java 5, o StringTokenizer deve ser substituído pelo método split.
E a classe StringBuilder deve substituir a classe StringBuffer.

O código do Hugo Pinho, hoje em dia, fica assim:"

Texto de ViniGodoy

Porque a o StringTokenizer deve ser substituido.

V

Por que o split faz a mesma coisa, de uma maneira mais rápida, mais simples e mais poderosa. Além disso, a classe foi mantida só por questões de legado.
Na dúvida, leia a última linha da descrição da classe, no Javadoc:
http://download.oracle.com/javase/1.5.0/docs/api/java/util/StringTokenizer.html

J

“Por que o split faz a mesma coisa, de uma maneira mais rápida, mais simples e mais poderosa. Além disso, a classe foi mantida só por questões de legado .”

Na documentação da Oracle não diz que o split e mais rápido,mais simples nem mais poderoso.Depois de dar uma googlada achei um link interessante.
Um teste realizado que transforma double e ints em uma string com um milhão de doubles deu isso aqui:

Scanner: 10642 ms
Split: 715 ms
StringTokenizer: 544ms
JFastParser: 290ms

Código: https://github.com/hughperkins/jfastparser

V

Não citei a documentão, era eu que estava falando isso.

Ele é mais poderoso por trabalhar com expressões regulares. Só isso já permite um conjunto muito mais complexo de tokens, e muito mais interessante também.

Ele é mais simples por retornar os dados em estruturas que podem ser percorridas com o for each. Basta comparar qualquer código usando split com um código usando o Tokenizer, para você ver que tem bem menos boilerplate.

Ele é mais rápido por usar o mecanismo de expressões regulares. Talvez, no caso exclusivo de tokens muito simples, como o espaço, realmente não seja. Mas essa não é a única situação onde precisamos quebrar dados em tokens. Seu benchmark trata apenas do caso relevante para a API JFastParser (quebrar uma String em doubles).

O que citei da documentação é a observação gigante da Oracle dizendo que a StringTokenizer deveria ser descontinuada. Isso também significa que provavelmente essa classe não terá otimizações da Oracle no futuro, enquanto a API de Regex certamente terá.

Criado 4 de abril de 2007
Ultima resposta 8 de out. de 2014
Respostas 10
Participantes 9