Ordenação sem Duplicatas TreeSet

9 respostas
R

E ai galera blz !

Estou com o seguinte problema estou tentando fazer uma ordenação de sem duplicatas utilizando a
classe treeset, mas nao esta dando certo o treeset assim como hashset não utiliza os metodos hashcode e equals ?
acabei fazendo assim.

Mas não sei se é o mais adequado.

public static void main(String args[]){

ArrayList<ClasseB> b = new ArrayList<ClasseB>();
	b.add(new ClasseB("Robson",1,"rln00@rln"));
	b.add(new ClasseB("Juka",2,"rln00@rln"));
	b.add(new ClasseB("Fernanda",3,"rln@rln"));
	b.add(new ClasseB("Aernanda",4,"rln@rln"));
	System.out.println(b);
	
	HashSet<ClasseB> c = new HashSet<ClasseB>();
	c.addAll(b);
	System.out.println(c);
	
	Set<ClasseB> order = new TreeSet<ClasseB>(c);
	System.out.println(order);
	
}

Obrigado.

9 Respostas

B

De acordo com a documentação do SortedSet, a ordenação é feita em classes que implementem a interface Comparable, ou por via um Comparator passado na criação da coleção, no caso o TreeSet.

R

Com relação a ordenação eu já implemente a CompareTo na ClasseB mas o que não consigo fazer com o treeSet
é parte de não conter duplicatas que o hashset faz.

Poderiam dar uma força ?

Valeu.

rodrigo.bossini

Leia o contrato que existe entre o hashcode e o equals na API. Faça com que sua “ClasseB” siga esse contrato.

B

robson.nunes:
Com relação a ordenação eu já implemente a CompareTo na ClasseB mas o que não consigo fazer com o treeSet
é parte de não conter duplicatas que o hashset faz.

Poderiam dar uma força ?

Valeu.

Todos os Sets não aceitam duplicatas, inclusive o TreeSet. Para evitar duplicatas, o Set usa o método equals que você deve sobreescrever na tua classe. A ordenação só acontece em SortedSets, que usa Comparable ou Comparator, como falei.

Exemplo:

public class Pessoa implements Comparable<Pessoa> {

	private long id;
	private String nome;

	public Pessoa(long id, String nome) {
		if (nome == null || nome.isEmpty())
			throw new IllegalArgumentException("O nome deve estar preenchido.");
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (id ^ (id >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Pessoa))
			return false;
		Pessoa other = (Pessoa) obj;
		if (id != other.id)
			return false;
		return true;
	}

	@Override
	public int compareTo(Pessoa o) {
		return nome.compareTo(o.nome);
	}
}
R

Então eu já fiz essa sobre escrita do equals e hascode mas pareçe que a classe TreeSet não esta chamando esses métodos só o de CompareTo que esta ok segue o código.
Pelo que percebi no modo Debug é que com a classe HashSet ele chama automaticamente o método hashcode
quando você utiliza add ou addall, mas utilizando TreeSet isso não esta aconteçendo.

ClasseA

public class  ClasseA {
	
	public static void main(String args[]){
	
		List<ClasseB> b = new ArrayList<ClasseB>();
		b.add(new ClasseB("Robson","aaa@"));
		b.add(new ClasseB("Juka","fff@"));
		b.add(new ClasseB("Maria","fff@"));
		
		Set<ClasseB> t = new TreeSet<ClasseB>();
		t.addAll(b);
			
		System.out.println(t);
	}
}


ClasseB

public class  ClasseB implements Comparable<ClasseB> {
	
	
	private String nome;
	private String email;
	
	public ClasseB(String nome, String email){
		
		this.nome = nome;
		this.email = email;
	}
	
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public int compareTo(ClasseB o) {
		
	return	this.nome.compareTo(o.getNome());
		
	}
	
	@Override
	public boolean equals(Object obj) {
		
		ClasseB b = (ClasseB) obj;
		
		return getEmail().equals(b.getEmail());
	}
	
	@Override
	public int hashCode() {
	
		return	this.email.hashCode();
		 
	}
	
	@Override
	public String toString() {
	
		return this.nome;
	} 
}
B

Está dando errado por que você não está seguindo uma outra regra de um SortedSet:

A ordem natural de um objeto, isto é, quando uma classe implementa Comparable, deve ser consistente com o equals da classe.

Em outras palavras se a.compareTo(b) == 0, então a.equals(b) == true.

No teu caso, você está usando o e-mail para fazer o equals e o hashcode, e o nome para fazer o compareTo. Você deveria usar somente nome ou somente o email em ambos os casos.

Se quiser depois ordenar por nome, crie um Comparator de ClasseB por nome, e passe como parâmetro para o TreeSet durante a sua instanciação.

R

E ai Bruno, blz mato o problema alterei tudo para nome ai ordenou e verificou se existia duplicatas.

Eu só tenho uma última dúvida por que eu consigo fazer ordenação e verificar duplicatas com tipos direfentes no CompareTo e no equlas utilizando o HashSet, mas não com TreeSet.

Valeu.

B

Só uma aula antes da explicação:

O hashcode serve para podermos usar uma técnica para separar os dados no que chamamos de buckets, ou baldes de dados. Isso serve para acelerar a pesquisa por um elemento dentro de um conjunto que use esses hashes para se orientar.

Por exemplo, temos os nomes ana, bruno, camila, danilo, eduardo e fábio. O hashcode dos nomes de A a B indicam que ficarão no balde 1, C a D no balde 2, E a F no 3. Colocamos todos esses nomes do HashSet.

Agora queremos colocar mais um fábio no conjunto. Num conjunto normal, o algorítmo verificaria cada um dos nomes um a um para ver se tem um outro fábio. Iria primeiro em ana, depois bruno, camila, até chegar no último.

Com o hashcode ele verifica que fábio está no balde 3. Ele vai direto até o balde e vê que tem somente eduardo e fábio dentro.

Como o hashcode é somente uma orientação, o equals é que faz o trabalho de verdade de comparação. Por isso que equals e hashcode tem que ser um consistente com o outro, pois se colocarem um elemento no balde errado, é capaz de não acharmos ele e o elemento será duplicado.

Voltando à pergunta, o HashSet não faz ordenações, somente evita duplicatas. Pelo que o nome dele indica, ele deve usar somente o hashcode e o equals, como disse acima, para evitar duplicatas.
Do outro lado temos o TreeSet. Este usa o compareTo para se guiar até o elemento que quer encontrar, já que que ele mantém tudo ordenado. Não precisa do hashcode nem do equals, já que ele requer que o equals seja consistente com o compareTo.

R

Blz valeu pelas explicações.

abs

Criado 9 de julho de 2009
Ultima resposta 11 de jul. de 2009
Respostas 9
Participantes 3