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

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

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…

É 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]) + "]");
        }
    }
}

[code]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);
}

}[/code]

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

Me ajudou tb , obrigado

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:

[code]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);  
}

}[/code]

Por isso é bom tomar cuidado ao copiar de tópicos velhos. :wink:

"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.

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

“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

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á.