Pular para o conteúdo

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

Dica publicada em Java / Miscelânea
Pedro Ferrarezi ferrarezux
Hits: 13.086 Categoria: Java Subcategoria: Miscelânea
  • Indicar
  • Impressora
  • Denunciar
O Viva o Linux depende da receita de anúncios para se manter. Ative os cookies aqui para nos patrocinar.
Não conseguimos carregar os anúncios. Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.

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;
    }
}
O Viva o Linux depende da receita de anúncios para se manter. Ative os cookies aqui para nos patrocinar.
Não conseguimos carregar os anúncios. Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.

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.

O Viva o Linux depende da receita de anúncios para se manter. Ative os cookies aqui para nos patrocinar.
Não conseguimos carregar os anúncios. Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.

Backup poderoso e automatizado combinando 7-Zip + head + cron

Ubuntu 12.04 com Gnome 3 - Tunando a Aparência com Temas e Ferramentas

Convertendo formato de vídeo OGV para AVI

Ubuntu 11.10 - Como usar o Notepad++ via Wine

Cálculo do desvio padrão no LibreOffice

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

Evento sobre Java na UFSCar

Melhorando a performance de sua Java Virtual Machine

Anti-aliasing para todos os componentes Java

Rodando páginas JSP no Apache

#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

Entre na sua conta para comentar.