HashSet: Qual a vantagem?[Resolvido]

12 respostas
Mantu

O HashSet, pelo que eu li, têm como principal vantagem estar baseada em um HashMap, proporcionando uma boa performance nas operações básicas(add, remove, contains e size)desde que o objeto inserido tenha uma implementação boa do hashCode().
Mas notei que esta classe não tem nenhum método para recuperar um objeto. Qual então a vantagem, ou o propósito de se utilizar um HashSet?

12 Respostas

ramilani12

Para vc recuprerar um objeto precisará de um objeto Iterator :
No javadoc


The iterators returned by this class’s iterator method are fail-fast:
if the set is modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the
Iterator throws a ConcurrentModificationException.
Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary,
non-deterministic behavior at an undetermined time in the future.

ViniGodoy

Acho que é pelo fato de você não ser obrigado a associar os objetos a uma chave.

Na verdade, é uma forma simples de “agrupar” uma série de objetos, sem repetições. Particularmente, posso contar nos dedos quando usei um HashSet. Geralmente usar um list é mais agradável.

E quanto à performance, só se isso for muito crítico para dar problema. Acho que não tem porque se preocupar com performance em códigos desse tipo, a menos que um profiler acuse…

Também não entendo porque não há um método get(int pos) num TreeSet, uma vez que, embora seja um set, é também ordenado.

Mantu

Desculpem, deixei a pergunta muito vaga…
Pegar o Iterator é algo comum a qualquer Set ou List. A minha dúvida é quando queremos recuperar um determinado objeto de dentro do HashSet. Num ArrayList, por exemplo, temos os métodos get, indexOf e lastIndexOf, que nos auxiliam a recuperar um elemento específico da nossa coleção. Não nada parecido no HashSet. Então, de que adianta eu ter performance no armazenamento, e não poder usufruir dessa mesma performance (partindo do pressuposto que o hashCode do elemento é um bom hashCode) na hora de recuperar o elemento?

ciczan

Ele não tem métodos para recuperar um elemento específico porque não é ordenado de nenhum jeito. Nem por índice nem por chave. Então não tem como encontrar um objeto.

Acho que esse Set só é útil quando vc for fazer um monte de inserção, remoção, etc, não quer elementos repetidos e vai ter que listar tudo só no final. Dai usa o iterator.

ViniGodoy

Pois é, nesse caso, não seria interessante que o TreeSet tivesse tais métodos?

Mantu

ViniGodoy:
Acho que é pelo fato de você não ser obrigado a associar os objetos a uma chave.

Também não entendo porque não há um método get(int pos) num TreeSet, uma vez que, embora seja um set, é também ordenado.


Um get(int pos) em um HashSet ou TreeSet até dá pra entender, porque a dita “posição” de um elemento pode mudar de acordo com as inserções e remoções na coleção. Mas será que não daria para utilizar algum mecanismo para termos algo como … … …
PUTZ… Agora, neste exato momento, escrevendo isso aqui que eu to vendo que é desnecessário, quase até nonsense, ter um método pra recuperar um determinado objeto de dentro de um set…
Primeiro, porque o lance de vc indicar uma “posição” de um elemento dentro do set é furado
Segundo, porque se fosse para termos um método, tipo assim:

public Object get(Object objProcurado)

Acho que não faria sentido… objProcurado seria exatamente o objeto que vc está procurando! Então, eu não precisaria recuperá-lo, pois ele já está comigo… Por isso que temos o método contains
Putz… viajei na maionese…
Valeu galera!

Mantu

Pois é, nesse caso, não seria interessante que o TreeSet tivesse tais métodos?
Então, com TreeSet rola uma gambiarrazinha nesse sentido…
Isso:

Object elem = myTreeSet.tailSet(objComparacao).first();

Ou isso:

Object elem = myTreeSet.headSet(objComparacao).last();
1112

Pois é, nesse caso, não seria interessante que o TreeSet tivesse tais métodos?

O TreeSet é ordenado de acordo com o Comparator/Comparable dos elementos adicionados, então acho que os únicos métodos que seriam interessantes seriam métodos para pegar o primeiro e último elementos. Ainda assim, mais adequado a essa necessidade seria usar um Collections.sort em uma List, assim não existe o overhead de ordenar os elementos a cada inserção.

ViniGodoy

#@®®¡$:

O TreeSet é ordenado de acordo com o Comparator/Comparable dos elementos adicionados, então acho que os únicos métodos que seriam interessantes seriam métodos para pegar o primeiro e último elementos. Ainda assim, mais adequado a essa necessidade seria usar um Collections.sort em uma List, assim não existe o overhead de ordenar os elementos a cada inserção.

Na verdade, para o primeiro e para o último existem métodos.

Mas não sei porque pegar um elemento do meio faça menos sentido do que pegar esses aí. Posso até concordar que, talvez pela implementação em árvore, isso não seja o mais adequado (assim como não é adequado ficar usando get por índices num LinkedList). Mas não vejo porque seria inedequado para a interface SortedSet.

Seria muito interessante ter um método para isso, sem ter que recorrer a “gambiarrazinhas”. Claro, é sempre bom ter algo assim na manga, mas gambi é sempre gambi.

1112

É verdade, os métodos existem, eu não tinha percebido.

Mas ainda não faz sentido pra mim pegar um elemento do meio. Como seria? Algo como pegar o nº elemento a partir do início ou do fim? Sei lá, eu acho isso meio estranho e, pelo menos no caso de TreeSet (que é a única implementação de SortedSet presente no SDK, se não me engano) seria uma “gambiarrazinha”.

Sei lá, talvez eu esteja confuso porque ainda não vi necessidade para tal. Pode me mostrar algum exemplo?

sergiotaborda

Mantu:
O HashSet, pelo que eu li, têm como principal vantagem estar baseada em um HashMap, proporcionando uma boa performance nas operações básicas(add, remove, contains e size)desde que o objeto inserido tenha uma implementação boa do hashCode().
Mas notei que esta classe não tem nenhum método para recuperar um objeto. Qual então a vantagem, ou o propósito de se utilizar um HashSet?

Antes de entender o que é um HashSet seria bom entender o que é um Set.Ajudaria a não pensar que HashSet teria que ter forma de pegar os objetos individualmente…
Um Set é um conjunto matemático, ou seja, é um conjunto de elementos todos diferentes e sem nenhum relação especial entre si.

Set é uma especialização porque só permite objetos de um certo tipo criando uma relação abstrata entre eles. Mas só.

Pq eu quero um Set ? porque ele impede repetição. Então se eu faço N .add() num set não tenho que verificar se o elemento já está lá. Num list eu teria que fazer isso manualmente, o que é menos eficiente.
Um conjunto de listeners é um exemplo classico. Não é necessário informar o mesmo listener do mesmo evento mais do que uma vez - pode até ser danoso - então um set é o ideal. O novo CopyOnWriteArraySet é excelente para este fim.

Qual a implementação mais rápida de um Set ?
Sendo que a sua função é apenas impedir repetições e iterar, o gargalo é saber com eficiência se o elemento já está no conjunto. Que melhor forma de fazer isso se não pela comparação de hashCode dos objetos ? E dai o nome HashSet.

Bom ,mas e se hashcode não for a melhor forma ? Ela é genérica, mas para casos em que existem mais relações entre os objetos não é a mais eficiente. Se os objetos são ordenáveis, TreeSet é muito melhor.

Isso é muito bonito, mas se eu quero manter a ordem de iteração ?
List resolveria o problema, mas eu não quero pegar os elementos, eu so quero iterar , na mesma ordem, pelos elementos. Então LinkedHashSet faz o trabalho. O uso de hashcode é irrelevante face à funcionalidade de manter a ordem de iteração que é o objetivo.

Mas e se eu só carrego o Set uma vez ?
Neste caso a procura por duplicados nem tem que ser assim tão eficiente podendo usar um array para guardar os elementos (que aumenta a eficiencia de iterar) e uso CopyOnWriteArraySet. Que tem outra vantagem, ele pode ser usado concorrentemente sem nenhum problema de causar uma falha na iteração.

Existem Set para todos os gostos e requisitos. Agora, querer obter um so elemento de um Set revela que algo está errado , ou com a escolha de Set em vez de List ou Queue , ou com a tentativa em si, que como já foi dito não faz sentido.

Contudo, para pegar o primeiro elementos basta fazer set.iterator.next() supondo que se sabe que o set tem elementos.

LPJava

assim acho que a pergunta do Mantu é tipo quer pegar o objeto que ta em tal local… tipo como array… seria isso? vc vai ter que usar o codigo hashing para recuperar o cara!! nao tem um ordenamento para codigos hashing… claro que existe um que a jvm faz… mas nao sabemos como é… por exemplo eu sei que uma ordenacao de int é 1…2…3. mas de codigo hashing? qual é? sei la… so a jvm que sabe… por isso o fato de usar o codigo hashSet segundo a kathy em resumo é isso:
hashSet() nao garante nenhum tipo de ordenacao. O desempenho aqui é bastante alto, pois usa o hashCode(), para identificacao.
O uso dessa interface(Set) é quando a ordenação não tem prioriade e sim de não ter duplicatas.

import java.util.*;
class SetTest{
	public static void main(String[] agrs){
		boolean[] ba = new boolean[4];
		//crio meu objeto set
		Set s = new HashSet();
		
		ba[0] = s.add("a");
		ba[1] = s.add(new Integer(42));
		ba[2] = s.add("a");
		ba[3] = s.add(new Object());
			
			for(int x = 0; x<ba.length; x++)
				System.out.print(ba[x] + " ");
			
			System.out.println("\n");
			//imprima os objetos
			for(Object o : s)
				System.out.println(o + " ");
	}
}

nao sei ajudei!! flw!!

Criado 6 de março de 2007
Ultima resposta 6 de mar. de 2007
Respostas 12
Participantes 7