Java hashtable probleem

Moderators: jkien, Xilvo

Gebruikersavatar
Berichten: 2.906

Java hashtable probleem

Wie kan mij deze bug uitleggen? Ik heb een class genaamd Order, een arraylist van Order-objecten en een Hashtable die aan iedere Order een vector van Order-objecten toekent.

Code: Selecteer alles

ArrayList<Order> orders;

Order ord1;

HashTable<Order, Vector<Order>> supports;

...

...

for(Order ord2 : orders){

if(ord1.equals(ord2)){

if(supports.get(ord1) == null){

   System.out.println("something went wrong");

}

if(supports.get(ord2) == null){

   System.out.println("something went wrong2");

}

}

}
Deze code print alleen "something went wrong". Dit is vreemd, aangezien ord1.equals(ord2) true geeft, zou je verwachten dat het niet uitmaakt of je supports.get(ord1) of supports.get(ord2) doet, dus zouden beide teksten geprint moeten worden. :S
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

ohja, vergeten erbij te vermelden: de class Order implementeert geen nieuwe equals() methode, dus het gaat hier gewoon om de equals() methode die is overgeërfd van Object.
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 7.224

Re: Java hashtable probleem

equals() vergelijkt references en geen values. Als obj1 en obj2 beide een null reference hebben, dan zal obj1.equals(obj2) true terug geven

De standaard equals() methode in Java is gelijk aan "=="
If I have seen further it is by standing on the shoulders of giants.-- Isaac Newton

Gebruikersavatar
Berichten: 5.609

Re: Java hashtable probleem

ohja, vergeten erbij te vermelden: de class Order implementeert geen nieuwe equals() methode, dus het gaat hier gewoon om de equals() methode die is overgeërfd van Object.
a)Daar heb je je probleem. De equals-methode van Object vergelijkt pointers, zoals Bart al aangaf, en mag je dus NOOIT gebruiken (idem met de hashcode). Dus object.clone().equals(object)==false

b)als je hashen wil gebruiken, MOET je dus zelf een methode equals en een methode hashcode implementeren.

c) hashtable mag je niet gebruiken, hij wordt deprecated. HashMap is het juiste alternatief.
What it all comes down to, is that I haven't got it all figured out just yet

And I've got one hand in my pocket and the other one is giving the peace sign

-Alanis Morisette-

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

Bart schreef:equals() vergelijkt references en geen values. Als obj1 en obj2 beide een null reference hebben, dan zal obj1.equals(obj2) true terug geven

De standaard equals() methode in Java is gelijk aan "=="
ja, dat snap ik, maar allebei de variabelen zijn niet null, dat heb ik gechecked.
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

317070 schreef:a)Daar heb je je probleem. De equals-methode van Object vergelijkt pointers, zoals Bart al aangaf, en mag je dus NOOIT gebruiken (idem met de hashcode). Dus object.clone().equals(object)==false

b)als je hashen wil gebruiken, MOET je dus zelf een methode equals en een methode hashcode implementeren.

c) hashtable mag je niet gebruiken, hij wordt deprecated. HashMap is het juiste alternatief.
Het is überhaupt nooit de bedoeling geweest om de equals() methode te gebruiken. Het probleem was dat supports.get(ord1) null geeft, terwijl supports.get(ord2) dat niet doet, terwijl ik dacht dat ord1 en ord2 toch echt naar hetzelfde object refereerden. De equals() methode heb ik hier dus alleen gebruikt om te checken of mijn hypothese klopte. En inderdaad blijken beide pointers naar hetzelfde object te verwijzen. Dus begrijp ik het probleem nog steeds niet. ;)
c) hashtable mag je niet gebruiken, hij wordt deprecated. HashMap is het juiste alternatief.
Bedankt voor de tip! ;)
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

Hangt hier werkelijk niemand rond die genoeg van java weet om mij dit probleem uit te leggen??? ;)
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 4.810

Re: Java hashtable probleem

Edit: Wat ik hier te zeggen had klopte niet ;)

Gebruikersavatar
Berichten: 4.810

Re: Java hashtable probleem

Heb je ord1 en ord2 al eens gewoon afgedrukt en gekeken of ze dezelfde referentie hebben?

Gebruikersavatar
Berichten: 5.609

Re: Java hashtable probleem

Hangt hier werkelijk niemand rond die genoeg van java weet om mij dit probleem uit te leggen??? ;)
Ik weet veel van Java, ik heb al op mijn eentje een full-blown media-managment programma gemaakt (lees: mp3 afspelen, binnen Java videos afspelen met de hulp van VLC-dll files die ik binnenhaalde via JNA, youtube-crawler en videos downloaden van youtube, dynamisch klassen binnenhalen die niet met mijn programma gecompiled zijn om als plugin te gebruiken, ...) Zie: http://sourceforge.net/projects/lyricscatcher/

Maar, als je je niet aan de regels van het coderen houdt (lees: niet zelf de equals en hashcode implementeert) dan kan uiteraard vanalles misgaan. De regel is:
http://www.ifs.tuwien.ac.at/ifs/lehre/eprog/javadoc/jdk/docs/api/java/lang/Object.html#hashCode%28%29 schreef:# If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

# It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
In jouw implementatie zijn de 2 bovenstaande regels dus niet vervuld. Als je de functies equals() en hashcode() niet geïmplementeerd hebt, is het nogal vanzelfsprekend dat het niet werkt.

Waarom het precies niet werkt is een veel moeilijkere vraag. Daarvoor moet je iets af kennen van de Java compiler en de JVM, en daar weet ik niets vanaf. Maar dat is dan ook een vrij zinloze vraag...

Edit: ik heb precies een stapje overgeslagen. De hashcode is afhankelijk van de JVM omwille van:
The default hashCode() method uses the 32-bit internal JVM address of the Object as its hashCode. However, if the Object is moved in memory during garbage collection, the hashCode stays constant. This default hashCode is not very useful, since to look up an Object in a HashMap, you need the exact same key Object by which the key/value pair was originally filed. Normally, when you go to look up, you don’t have the original key Object itself, just some data for a key. So, unless your key is a String, nearly always you will need to implement a hashCode and equals method on your key class. Object.hashCode in a native method.
http://mindprod.com/jgloss/hashcode.html
What it all comes down to, is that I haven't got it all figured out just yet

And I've got one hand in my pocket and the other one is giving the peace sign

-Alanis Morisette-

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

Heb je ord1 en ord2 al eens gewoon afgedrukt en gekeken of ze dezelfde referentie hebben?
hoe doe je dit in java? Bedoel je het geheugenadres waar ze naar verwijzen afdrukken?
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

@317070: Dus om HashTable / HashMap te gebruiken moet je eerst helemaal zelf een eigen HashCode gaan lopen definiëren? Niet echt praktisch....

Is er dan geen andere datastructuur die ik kan gebruiken om simpelweg objecten van klasse A naar objecten van klasse B te mappen? Ik kan wel wat manieren verzinnen om zoiets zelf te implementeren, maar ik had toch wel gedacht dat er een ready-to-use datastructuur was die dat voor je doet.
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 5.609

Re: Java hashtable probleem

Math-E-Mad-X schreef:@317070: Dus om HashTable / HashMap te gebruiken moet je eerst helemaal zelf een eigen HashCode gaan lopen definiëren? Niet echt praktisch....

Is er dan geen andere datastructuur die ik kan gebruiken om simpelweg objecten van klasse A naar objecten van klasse B te mappen? Ik kan wel wat manieren verzinnen om zoiets zelf te implementeren, maar ik had toch wel gedacht dat er een ready-to-use datastructuur was die dat voor je doet.
Meuh, dat is toch geen werk om dat zelf te implementeren.

Uit mijn duim

Code: Selecteer alles

public int hashCode()

{

   int hash = 0;

   hash = 31 * hash + field1.hashcode();

   hash = 31 * hash + field2.hashcode();

   hash = 31 * hash + field3.hashcode();

   hash = 31 * hash + field4.hashcode();

   return hash;

}
gewoon op al je velden die je wil hebben in je code invullen. Je hashcode moet ook helemaal niet goed werken om te werken...

Nu als ik het goed begrijp gebruik je toch identieke objecten om dan terug in je hashtable op te zoeken. Is het dan niet logischer om gewoon een veld met object B binnen je object A op te slaan?
What it all comes down to, is that I haven't got it all figured out just yet

And I've got one hand in my pocket and the other one is giving the peace sign

-Alanis Morisette-

Gebruikersavatar
Berichten: 2.906

Re: Java hashtable probleem

In jouw implementatie zijn de 2 bovenstaande regels dus niet vervuld.
Sorry, dit snap ik niet.

punt 1) De default HashCode gebruikt toch juist het adres? Dus als twee objecten hetzelfde adres hebben, hebben ze logischerwijs ook dezelfde HashCode.

punt 2) Dit punt lijkt me sowieso niet van toepassing op mijn probleem, omdat het bij mij juist om twee objecten gaat die wel hetzelfde adres hebben.

Blijkbaar begrijp ik je helemaal verkeerd, want voor zover ik zie zijn deze twee punten dus wel vervuld. ;)
Nu als ik het goed begrijp gebruik je toch identieke objecten om dan terug in je hashtable op te zoeken. Is het dan niet logischer om gewoon een veld met object B binnen je object A op te slaan?
Ja, maar het probleem is dat ik deze klassen niet zelf geschreven heb, ze komen uit een framework.
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Gebruikersavatar
Berichten: 5.609

Re: Java hashtable probleem

Code: Selecteer alles

ArrayList<Order> orders;

Order ord1;

HashTable<Order, Vector<Order>> supports;



...

...



for(Order ord2 : orders){

	if(ord1 == ord2){

		if(supports.get(ord1) == null){

		   System.out.println("something went wrong");

		}

		if(supports.get(ord2) == null){

		   System.out.println("something went wrong2");

		}					

	}

}
Wat gebeurt er met deze code? Misschien is de equals() methode in je framework overridden, zonder dat je het weet, maar de hashcode() niet.
What it all comes down to, is that I haven't got it all figured out just yet

And I've got one hand in my pocket and the other one is giving the peace sign

-Alanis Morisette-

Reageer