Extendendo a classe ArrayList para criar listas sem repetição

Publicado por Pedro Ferrarezi em 20/12/2013

[ Hits: 12.290 ]

 


Extendendo a classe ArrayList para criar listas sem repetição



Olá, amigos do VOL.

Hoje, deixo uma dica sobre como criar, rapidamente, listas de vetores/arrays sem repetição, em Java.

Estou deixando essa dica, porque depois de "googlar" por horas e horas, não achei um código decente que fizesse o acima.

O que mais se acha na Net, são usuários avançados sugerindo implementar comparable e iterator. Mas isso gera um código grande e complexo, e nem sempre atende a todas às necessidades.

Eu até vi alguns usuários bravos no Stack Overflow dizendo que em C++, a classe std::Set provê isso com facilidade, e que Java só faz a gente passar raiva. Mas, eu acho que não é bem por aí. Java também te dá isso, mas por um caminho mais longo, só isso.

A solução que acabei chegando depois de muita dor, tentativa e erro, foi estender a classe ArrayList e sobrecarregar o método contains(), e é isso que vou explicar como fazer.

Primeiro, crie uma classe que estende a classe ArrayList, como abaixo:

import java.util.ArrayList;
import java.util.Arrays;

public class Lista<T> extends ArrayList<T>{

    public Lista() {
        super(); //chame o construtor de ArrayList
    }

    /*Esse método sobrecarrega o metodo contains, e irá funcionar
    com arrays de objetos. Você pode sobregarregar, sobrescrever
    ou adicionar mais métodos a esta classe, de forma que
    ela fique ainda mais poderosa, e usar ela, em vez de ArrayList.
    */

    public boolean contains(Object[] o){
        //percorre o bjeto 'Lista':
        for(int i=0; i< this.size(); i++){
            /* cria um array de objetos e faz um 'type-cast'
            desta própria classe atribuindo a ele o valor do
            elemento, e isso para cada elemento, de forma que
            todos os elementos sejam tratados como arrays de
            objetos:
            */

            Object[] toCompare = (Object[])this.get(i);
            /* através do metodo equals da classe Arrays, e do loop
            for-each, verifica se algum elemento do array candidato ao
            add() já está adicionado na lista, se sim é retornado true,
            se não, é retornado false.
            */

            if(Arrays.equals(o, toCompare)){
                return true;
            }
        }
        return false;
    }
}

Para testar se a classe está funcionando, crie uma classe principal e chame-a, tente adicionar registros repetidos e teste o conteúdo das listas de arrays depois, assim:

public static void main(String[] args) {
Lista<Object[]> lista = new Lista<Object[]>(); //Instancia a classe que criamos

        for(int i=0; i<100; i++){ //tenta inserir 100x a mesma coisa
            if(!lista.contains(new Object[]{ "bbb", true, 132.0, 1234 })) //Observe que existem vários tipos de dados nesse array
                lista.add(new Object[]{ "bbb", true, 132.0, 1234 });

            if(!lista.contains(new Object[]{ "aaa", false, 132.0, 1234 }))
                lista.add(new Object[]{ "aaa", false, 132.0, 1234 });
        }

        for(int j=0; j<lista.size(); j++){
            for(int c=0; c<lista.get(j).length; c++){
                System.out.print(lista.get(j)[c]+"-");
            }
            System.out.print("\n");
        }
    }

A saída no console, será:
bbb-true-132.0-1234-
aaa-false-132.0-1234-

Foram inseridos apenas 2 arrays na lista. :)

Um abraço a todos.
Espero que ajude.

Outras dicas deste autor

Montando um servidor de remote desktop com NX Server

Como mudar o teclado do Debian em uma máquina virtual configurada em outro SO

Debian/Ubuntu - Conectando banco MySQL via rede com Java

Convertendo formato de vídeo OGV para AVI

Organizando bibliotecas .jar + projeto NetBeans em único arquivo .jar

Leitura recomendada

Configurando ambiente Java no sistema operacional Linux

Setando o ícone de um JFrame de Java

Empresa desenvolve CRM que funciona em Linux

Rodando páginas JSP no Apache

Mantendo seu Eclipse atualizado

  

Comentários
[1] Comentário enviado por maiconramones em 20/12/2013 - 10:27h

Prezado Pedro,

Acho que você está começando a programar em Java, a sua solução não é a mais recomendada. Porque?

O Java já possui um conjunto de classes que não permitem elementos duplicados. Essas classes implementam a interface Set, você pode conferir mais informações na documentação aqui -> http://docs.oracle.com/javase/7/docs/api/index.html?java/util/Set.html.
Nesse link (http://javafree.uol.com.br/artigo/847654/) em português do JavaFree tem uma excelente explicação sobre as classes da API padrão que trabalham com coleções.

Espero ter ajudado

[2] Comentário enviado por ferrarezux em 20/12/2013 - 12:29h

Obrigado maiconramones. Mas leia o que eu disse na minha dica por favor.

[3] Comentário enviado por aronrodrigues em 06/01/2014 - 11:24h

Pedro, o que o Maicon falou é verdade.

"O que mais se acha na Net, são usuários avançados sugerindo implementar comparable e iterator. Mas isso gera um código grande e complexo, e nem sempre atende a todas às necessidades. "

O que você está fazendo no seu ArrayList é a mesma coisa que a interface Set faz.

Utiliza o comparable para verificar se o objeto já existe. Só que no seu código, a cada inserção você varre a lista (o que torna seu codigo MUITO lento).

Faça o teste, com um Set e com sua classe, para ver o resultado. (tente a partir de 100.000 elementos para ter noção do tempo).

Além disso sua classe tem um GRANDE problema, que é a de não ser aceita por outras bibliotecas (por exemplo ORM). Se você persistir sua classe no banco, o que o container vai te retornar será uma interface de List. E não da sua classe.

Para fazer do jeito certo, basta você usar o Set (vai funcionar igualizinho sua classe).

A interface Comparable (metodo compare), só deve ser sobrescrita se você quiser mudar a verificação padrão (exatamente o mesmo objeto) para uma comparação por exemplo, pelo ID.

Se quiser, me mande um email que te explico direitinho...



Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts