HashSet Intrujão! A API está mentindo para mim!

15 respostas
Alkamavo

valeu...eu tb tou a tentar fazer com o HashSet...mas ele ta deixando inserir objectos iguais...

aqui esta a classe vertice

package dataStrutures;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;



public class Main {

	/**
	 * @param args
	 */
	
	public static class Vertice implements Comparable {
		private String cidade;
		private int hora;

		public Vertice(String cidade, int hora) {

			this.cidade = cidade;
			this.hora = hora;
		}

		public Vertice() {
		}

		public int gethora() {
			return hora;
		}

		public void sethora(int v_1) {
			this.hora = v_1;
		}

		public String getcidade() {
			return this.cidade;
		}

		public void setCidade(String city) {
			this.cidade = city;
		}

		public String toString() {
			return " " + this.cidade + " " + this.hora;
		}

		@Override
		public int compareTo(Object o) {

			int value = 0;
			if (this.hora < ((Vertice) o).hora) {
				value = -1;
			} else if (this.hora > ((Vertice) o).hora) {
				value = 1;
			} else if (this.hora == ((Vertice) o).hora) {
				value = 0;
			}
			return value;

		}

		public boolean equals(Vertice xpto) {
			if (this.cidade.equals(xpto.getcidade())
					&& this.hora == xpto.gethora()) {
				return true;
			} else
				return false;
		}
	}
a main:
public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		ArrayList<Arcos> arcos = new ArrayList<Arcos>();

		String[] data = new String[5];

		int n_cidades = in.nextInt();

		String cidade_partida = in.next();

		String cidade_chegada = in.next();

		int hora_chegada = in.nextInt();

		int numero_voos = in.nextInt();

		in.nextLine();

		HashSet<Vertice> vertices = new HashSet<Vertice>();

		Vertice v_inicial = new Vertice(cidade_partida, 0);
		Vertice v_final = new Vertice(cidade_chegada, hora_chegada + 30);

		changeHour(v_final);

		vertices.add(v_inicial);
		vertices.add(v_final);
		for (int x = 0; x < numero_voos; x++) {

			data = in.nextLine().split(" ");
			Vertice v_partida = new Vertice(data[0], Integer.parseInt(data[3]));
			Vertice v_chegada = new Vertice(data[1],
					Integer.parseInt(data[4]) + 30);
			changeHour(v_chegada);
			if (!vertices.contains(v_partida)) {
				vertices.add(v_partida);
			}

			if (v_chegada.gethora() <= hora_chegada
					&& !vertices.contains(v_chegada)) {
				vertices.add(v_chegada);

			}
		}

		System.out.println(vertices.toString());

	}

	public static void changeHour(Vertice aux) {

		if (String.valueOf(aux.gethora()).substring(2, 4).equals("60")) {
			// aux.setHour((x+1));
			aux.sethora(Integer.parseInt((String
					.valueOf((Integer.parseInt(String.valueOf(aux.gethora())
							.substring(0, 2)) + 1)) + "00")));
		}
	}

no final eu quero apenas 10 vertices neste hashSet, mas ele ta aceitar valores ou objectos repetidos!!! brincandeira....

Output:

[ berlin 1530,  lisbon 1000,  paris 1130,  london 1130,  london 1130,  lisbon 0,  london 1130,  paris 1500,  berlin 1300,  paris 1130,  lisbon 1300,  paris 1330,  london 1500,  lisbon 1300,  paris 1330,  london 1340,  berlin 1300,  lisbon 1000]

15 Respostas

Alkamavo

resolvido…

o segredo estava no equals, o hashSet para ver se o objecto esta repetido usa o equals(Object xpto) tempos de redefinir este metodo na classe que criamos para o nosso objecto mas com o parametro Object, na comparação fazemos uma cast para o tipo do nosso objecto e kuando ele usar (HashSet) usa como deve ser…

aqui esta:

public boolean equals(Object o) { if (this.cidade.equals(((Vertice) o).getcidade()) && this.hora == ((Vertice) o).gethora()) { return true; } else return false; }

Java_Player

Outra coisa:

Quando você sobrescreve o equals() tem que sobrescrever o hashCode() também.

jmoreira

Cara, dúvidas deste tipo, não vale a pena ser colocada em um forum.
Normalmente é erro de lógica. O cerebro, se esforça-lo um pouquinho, consegue resolver sozinho.
Pense nisso.

Paulo_Silveira

O erro é sem duvida o que o Java Player falou

Voce nao reescreveu o hashCode().

Reescreva-o, nesse caso, dessa maneira, por exemplo:

public int hashCode() {
  return this.hora * this.cidade.hashCode();
}

Da pra melhorar bastante a funcao de hash ainda.

sergiotaborda

Paulo Silveira:

public int hashCode() {
  return this.hora * this.cidade.hashCode();
}

Da pra melhorar bastante a funcao de hash ainda.

basta usar ^ em vez de *

public int hashCode() {
  return this.hora ^ this.cidade.hashCode();
}
Paulo_Silveira

Melhora, mas isso ainda é BEM pouco. Voce precisa somar numeros e fazer shifts para evitar zeros e distribuir melhor os bits que tem maior probabilidade de estarem ligados, e como esse campo é HORAS, so os ultimos bits estarao acesos, e o XOR da parte da esquerda vai sempre se comportar de acordo com a String, gerando colisoes PRA CARAMBA dependentes de String ja que os Mapas do java infelizmente usam potencia de 2 em relacao a numero de buckets. Mas isso tem importancia nula pra ser sincero, tanto o XOR, multiplicacao ou mesmo soma ai nao vai impactar significativamente a performance sentida dele.

sergiotaborda

Paulo Silveira:
sergiotaborda:

basta usar ^ em vez de *

Melhora, mas isso ainda é BEM pouco. Voce precisa somar numeros e fazer shifts para evitar zeros e distribuir melhor os bits que tem maior probabilidade de estarem ligados, e como esse campo é HORAS, so os ultimos bits estarao acesos, e o XOR da parte da esquerda vai sempre se comportar de acordo com a String, gerando colisoes PRA CARAMBA dependentes de String ja que os Mapas do java infelizmente usam potencia de 2 em relacao a numero de buckets. Mas isso tem importancia nula pra ser sincero, tanto o XOR, multiplicacao ou mesmo soma ai nao vai impactar significativamente a performance sentida dele.

O objetivo não é criar o hashcode mais eficiente do mundo, apenas o mais fácil de produzir e entender (legibilidade do codigo). Usar * pode implicar que existe uma operação matemática e isso não é verdade. Então teria que criar um comentário explicando que * é melhor que ^ porque tudo isso que vc escreveu. com ^ já se sabe que é uma operação binária. Só isso.

P.S. Esqueci do mais importante: Usar * pode estourar o espaço do int, ^ nunca fará isso.

B

Alguém sabe de algum gerador de hashCode?

Paulo_Silveira

eclipse, menu source, generate equals and hashcode. prepare-se para obter bem mais do que voce precisa.

victorwss

java.util.Random :lol: :lol: :lol: :lol: :lol: :smiley: :smiley: :smiley: :smiley: :smiley: :lol: :lol: :lol: :lol: :lol: :twisted: :twisted: :twisted: :twisted: :lol: :shock:

sergiotaborda

java.util.Random :lol: :lol: :lol: :lol: :lol: :smiley: :smiley: :smiley: :smiley: :smiley: :lol: :lol: :lol: :lol: :lol: :twisted: :twisted: :twisted: :twisted: :lol: :shock:

Essa teve graça. Só é pena que não funciona como gerador de hashcode.

victorwss

java.util.Random :lol: :lol: :lol: :lol: :lol: :smiley: :smiley: :smiley: :smiley: :smiley: :lol: :lol: :lol: :lol: :lol: :twisted: :twisted: :twisted: :twisted: :lol: :shock:

Essa teve graça. Só é pena que não funciona como gerador de hashcode.

Captain Obvious!

sergiotaborda

java.util.Random :lol: :lol: :lol: :lol: :lol: :smiley: :smiley: :smiley: :smiley: :smiley: :lol: :lol: :lol: :lol: :lol: :twisted: :twisted: :twisted: :twisted: :lol: :shock:

Essa teve graça. Só é pena que não funciona como gerador de hashcode.

Captain Obvious!

No forum avançado espero bem que seja obvio … mas hei! sobre-escrever hashCode também era… :twisted:

Paulo_Silveira

sergiotaborda:

Essa teve graça. Só é pena que não funciona como gerador de hashcode.

se voce for sortudo… funciona! :slight_smile:

tem um outro engracado que funciona sempre:

public int hashCode() { return 0; }

juro que ja vi gente fazendo isso. é uma carroça a la ArrayList, mas funciona.

Rubem_Azenha

Tem esse aí: http://commons.apache.org/lang/apidocs/org/apache/commons/lang/builder/HashCodeBuilder.htm

Criado 28 de junho de 2008
Ultima resposta 3 de jul. de 2008
Respostas 15
Participantes 8