Quais as interfaces necessárias a classe precisa implementar para que possa ser usada num HashSet, evitando objetos repetidos.
A classe em questao chama-se Habilidade e se o campo codHabilidade for igual considera-se o objeto igual.
Eu ja implementei o metodo equals retornando true se os codHabilidade dos objetos comparados forem iguais, já implementei a interface Comparable (método compareTo retornando 0 caso os codHabilidade sejam iguais), e ainda está colocando elementos repetidos no HashSet.
[quote=hill]Quais as interfaces necessárias a classe precisa implementar para que possa ser usada num HashSet, evitando objetos repetidos.
A classe em questao chama-se Habilidade e se o campo codHabilidade for igual considera-se o objeto igual.
Eu ja implementei o metodo equals retornando true se os codHabilidade dos objetos comparados forem iguais, já implementei a interface Comparable (método compareTo retornando 0 caso os codHabilidade sejam iguais), e ainda está colocando elementos repetidos no HashSet.[/quote]
Um HashSet é um HashMap onde chave == valor.
Para inserir elementos em um HashSet você precisa implementar corretamente public boolean equals (Object o) e public int hashCode(). Não é preciso implementar Comparable.
[quote=thingol]Um HashSet é um HashMap onde chave == valor.
[/quote]
Huh? Não entendi. Não é o HashMap que usa um HashSet para guardar chaves? Aí um HashSet é um HasMap, que usa um HashSet, que é um HashMap, que usa um HashSet, que é um…
[quote=renato3110][quote=thingol]Um HashSet é um HashMap onde chave == valor.
[/quote]
Huh? Não entendi. Não é o HashMap que usa um HashSet para guardar chaves? Aí um HashSet é um HasMap, que usa um HashSet, que é um HashMap, que usa um HashSet, que é um…
[/quote]
Bom, eu fui pela descrição do Javadoc (This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.).
Vou dar uma olhada no fonte das duas classes para ver o que veio primeiro, o ovo (HashSet) ou a galinha (HashMap).
public class HashSet extends AbstractSet
implements Set, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap();
}
Aham, nem o ovo nem a galinha - talvez um biscoito e uma jarra de biscoitos; a implementação da Sun de um HashSet contém um HashMap (ele não é um HashMap).
Desculpe, não entendi o porque de implementar o metodo int hashCode. Como acontece essa distinção entre objetos quando sao colocados no Set ? Não eh através do metodo boolean equals(Object o) ? Porque se fosse assim, da forma como esta implementado o equals, duas Habilidade com codHabilidade iguais não poderiam ser inseridas, não eh mesmo ? E como é feita a implementação do método int hashCode nessa lógica simples do meu problema ?
Porque quando você precisa pesquisar seus objetos, que por um acaso estão armazenados numa estrutura de dados chamada tabela de hash,
o hashCode() agiliza a busca, ou faz ela não funcionar…
Seus Habilidade iguais devem estar sendo colocados no set porque retornam hash codes diferentes para objetos iguais.
Seu equals pode ser melhorado. Resumindo, o hash code deve retornar um número baseado na identidade do objeto, ou seja, baseado no equals(). Repita isso como um mantra:
Ao alterar equals(), provavelmente você precisa fazer o mesmo com hashCode().
Eu tava escrendo um texto sobre isso, talvez ano que vem tenha algo pronto :mrgreen: Você tá precisando ler um material sobre igualdade de objetos em Java, incluindo o equals() e o hashCode().
Tinha um tópico maneiro que acho que sumiu, mas olha esse link aqui por enquanto, e googla também.
Rode este programa. Ele demonstra o que ocorre se uma classe não define hashCode direito.
import java.util.*;
/**
* Esta classe implementa equals e hashCode.
*/
class Cliente {
private String nome = "";
private String endereco = "";
public Cliente(String pNome, String pEndereco) { nome = pNome; endereco = pEndereco; }
public String getNome() { return nome; } public void setNome(String pNome) { nome = pNome; }
public String getEndereco() { return endereco; } public void setEndereco(String pEndereco) { endereco = pEndereco; }
public String toString() { return "nome=" + nome + ", endereco=" + endereco; }
public boolean equals (Object o) {
if (!(o instanceof Cliente)) return false;
if (o == this) return true;
Cliente c = (Cliente) o;
// só para simplificar estou supondo que nenhum dos campos é null
return nome.equals(c.getNome()) && endereco.equals(c.getEndereco());
}
public int hashCode() {
int ret = nome.hashCode();
ret = ret * 37 + endereco.hashCode();
// se houver mais campos, vá repetindo a expressão acima "ret = ret * 37 + hashCode do proximo campo"
// por exemplo, ret = ret * 37 + telefone.hashCode();
return ret;
}
}
/**
* Esta classe implementa equals, mas não hashCode.
*/
class Cliente2 {
private String nome = "";
private String endereco = "";
public Cliente2(String pNome, String pEndereco) { nome = pNome; endereco = pEndereco; }
public String getNome() { return nome; } public void setNome(String pNome) { nome = pNome; }
public String getEndereco() { return endereco; } public void setEndereco(String pEndereco) { endereco = pEndereco; }
public String toString() { return "nome=" + nome + ", endereco=" + endereco; }
public boolean equals (Object o) {
if (!(o instanceof Cliente2)) return false;
if (o == this) return true;
Cliente2 c = (Cliente2) o;
// só para simplificar estou supondo que nenhum dos campos é null
return nome.equals(c.getNome()) && endereco.equals(c.getEndereco());
}
}
class TestHashSet {
public static void main(String[] args) {
HashSet<Cliente> clientes = new HashSet<Cliente>();
clientes.add (new Cliente ("Luis Inacio", "Palacio da Alvorada"));
clientes.add (new Cliente ("Fernandinho Beira-Mar", "Presidente Bernardes"));
clientes.add (new Cliente ("Fernandinho Beira-Mar", "Presidente Bernardes"));
System.out.println (clientes); // deve aparecer só uma vez o sr. Fernandinho
HashSet<Cliente2> clientes2 = new HashSet<Cliente2>();
clientes2.add (new Cliente2 ("Luis Inacio", "Palacio da Alvorada"));
clientes2.add (new Cliente2 ("Fernandinho Beira-Mar", "Presidente Bernardes"));
clientes2.add (new Cliente2 ("Fernandinho Beira-Mar", "Presidente Bernardes"));
System.out.println (clientes2); // O sr. Fernandinho aparece duas vezes.
}
}
Muito obrigado rapaziada, isso resolveu o problema aqui.
Vou pesquisar + sobre esse assunto, mas o q vcs postaram fez toda a diferença.
[]´s[size=9][/size]