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