Java TYS
Author |
Message |
Hikaru79
|
Posted: Mon Jan 21, 2008 9:58 pm Post subject: Java TYS |
|
|
I noticed that a lot of other, fairly obscure, languages have TYS' (Io, anyone?), but Java doesn't; since it's a popular language, and I love TYS', here I go
I'll get things started.
Java: | import java.util.*;
class Foo {
private String name;
public Foo (String name ) {
this. name = name;
}
public String getName () {
return name;
}
public boolean equals (Foo otherFoo ) {
return this. getName(). equals(otherFoo. getName());
}
public int hashCode () {
return name. hashCode();
}
}
public class Test {
public static void main (String [] args ) {
HashMap<Foo, String> test = new HashMap<Foo, String> ();
Foo firstFoo = new Foo ("foo");
test. put(firstFoo, firstFoo. getName());
Foo secondFoo = new Foo ("foo");
System. out. println("Equals: " + firstFoo. equals(secondFoo ));
System. out. println("Contains: " + test. containsKey(secondFoo ));
System. out. println("Why is the first statement true, but the second false!?");
System. out. println("I overloaded hashCode and equals, so it should work!");
System. out. println("At least, according to http://java.sun.com/javase/6/docs/api/java/util/Map.html#containsKey(java.lang.Object) it should!");
System. out. println("So where's the problem?");
System. exit(- 1);
}
}
|
The problem is explained in the println's at the end there. What is causing the "strange" behaviour, and how would you fix it so that it works as reasonably expected?
I encountered this "bug" in some of my own code; actually in my code, it was a ConcurrentHashMap in a (very) multithreaded program, so for a very long time I assumed it was a concurrency problem, and tried to find problems with my synchronization.
When that didn't work, I decided to see if the problem could be reproduced in a single thread. Oh, there it is. Oops .
The actual problem has nothing to do with threads; it's much simpler than that.
Enjoy ![Very Happy Very Happy](images/smiles/icon_biggrin.gif) |
|
|
|
|
![](images/spacer.gif) |
Sponsor Sponsor
![Sponsor Sponsor](templates/subSilver/images/ranks/stars_rank5.gif)
|
|
![](images/spacer.gif) |
HeavenAgain
![](http://compsci.ca/v3/uploads/user_avatars/139122102045e603120b143.jpg)
|
Posted: Mon Jan 21, 2008 10:09 pm Post subject: RE:Java TYS |
|
|
first one is true, because you are simply comparing the string, which they are equal, and now the 2nd one is a bit tricky... you are saying if the map contains the "reference" to secondFoo, not the String itself... and so it doesnt
if you try Foo secondFoo = firstFoo; then i think this will work...
tricky part is the String and reference instead of the actual "value" or at least i think ![Razz Razz](http://compsci.ca/v3/images/smiles/icon_razz.gif) |
|
|
|
|
![](images/spacer.gif) |
HellblazerX
![](http://www.plamania.co.kr/shopimages/plmtest/2910040000213.jpg)
|
Posted: Mon Jan 21, 2008 10:21 pm Post subject: RE:Java TYS |
|
|
That, or you could make your Foo class Comparable, and make your own compareTo () method that the HashMap will use. |
|
|
|
|
![](images/spacer.gif) |
Hikaru79
|
Posted: Mon Jan 21, 2008 10:23 pm Post subject: Re: RE:Java TYS |
|
|
HeavenAgain @ Mon Jan 21, 2008 11:09 pm wrote: first one is true, because you are simply comparing the string, which they are equal, and now the 2nd one is a bit tricky... you are saying if the map contains the "reference" to secondFoo, not the String itself... and so it doesnt
if you try Foo secondFoo = firstFoo; then i think this will work...
tricky part is the String and reference instead of the actual "value" or at least i think ![Razz Razz](http://compsci.ca/v3/images/smiles/icon_razz.gif)
Well, yes, it's no mystery why equals() returns true; but if you read the API docs, apparently containsKey() simply uses equals() to decide if the key exists -- so if WE get a true from equals(), why doesn't the HashMap?
Doing secondFoo = firstFoo doesn't work either You're not quite on the right track...
HellblazerX wrote: That, or you could make your Foo class Comparable, and make your own compareTo () method that the HashMap will use.
Try it and see I think you'll find that doesn't work. HashMap doesn't need something to be Comparable, it just needs equals()/hashCode(). |
|
|
|
|
![](images/spacer.gif) |
HeavenAgain
![](http://compsci.ca/v3/uploads/user_avatars/139122102045e603120b143.jpg)
|
Posted: Mon Jan 21, 2008 10:29 pm Post subject: RE:Java TYS |
|
|
well, yeah i just tried using Foo secondFoo = firstFoo; and both give me true...
and you are having 2 reference types here, one is the address to the Foo object, and after that it is another address to the String name.... by using equals you are only comparing the first reference, which is the Foo and Foo class, obviously they are not equal or am i not making any sense here... |
|
|
|
|
![](images/spacer.gif) |
HellblazerX
![](http://www.plamania.co.kr/shopimages/plmtest/2910040000213.jpg)
|
Posted: Mon Jan 21, 2008 10:33 pm Post subject: RE:Java TYS |
|
|
Does it have anything to do with your hashCode () method? It's possible the two hashcodes for your String aren't the same. |
|
|
|
|
![](images/spacer.gif) |
Hikaru79
|
Posted: Mon Jan 21, 2008 10:40 pm Post subject: Re: RE:Java TYS |
|
|
HeavenAgain @ Mon Jan 21, 2008 11:29 pm wrote: well, yeah i just tried using Foo secondFoo = firstFoo; and both give me true... ![Rolling Eyes Rolling Eyes](http://compsci.ca/v3/images/smiles/icon_rolleyes.gif)
Hm, sorry, you're right; it would, but this is sort of sidestepping the problem. I'm defining my own equals() for the purpose of being able to equate different objects which have a name in common (of course in this case, Foo only HAS a name, but it could easily carry other data as well). Your solution will only work if the two references are literally pointing at the same thing.
HeavenAgain wrote: and you are having 2 reference types here, one is the address to the Foo object, and after that it is another address to the String name.... by using equals you are only comparing the first reference, which is the Foo and Foo class, obviously they are not equal ![Shocked Shocked](images/smiles/icon_eek.gif) or am i not making any sense here...
I'm not sure what you mean here. Both firstFoo and secondFoo are Foo references. I can compare them for equality and even though they are two different references, they give me that they are equal (this is good). But when I put one into the HashMap, it fails to recognize firstFoo as being equal (in the sense I defined it) to secondFoo. Why?
Hint: It doesn't really have anything to do with references. It has more to do with method overloading and polymorphism. This is a big hint
HellBlazerX wrote: Does it have anything to do with your hashCode () method? It's possible the two hashcodes for your String aren't the same.
Nope, equal Strings have equal hashCodes(), but you're getting closer ![Smile Smile](images/smiles/icon_smile.gif) |
|
|
|
|
![](images/spacer.gif) |
HellblazerX
![](http://www.plamania.co.kr/shopimages/plmtest/2910040000213.jpg)
|
Posted: Mon Jan 21, 2008 10:48 pm Post subject: RE:Java TYS |
|
|
Equals () isn't properly overloaded because the parameter passed in isn't the same? O btw, I don't Java rite now so i can't test these out. |
|
|
|
|
![](images/spacer.gif) |
Sponsor Sponsor
![Sponsor Sponsor](templates/subSilver/images/ranks/stars_rank5.gif)
|
|
![](images/spacer.gif) |
Hikaru79
|
Posted: Mon Jan 21, 2008 10:52 pm Post subject: Re: RE:Java TYS |
|
|
HellblazerX @ Mon Jan 21, 2008 11:48 pm wrote: Equals () isn't properly overloaded because the parameter passed in isn't the same? O btw, I don't Java rite now so i can't these out.
Bingo In what sense is it not 'passed in the same'? How would you modify this so it works?
But your answer is correct! (though vague, for now) |
|
|
|
|
![](images/spacer.gif) |
HellblazerX
![](http://www.plamania.co.kr/shopimages/plmtest/2910040000213.jpg)
|
Posted: Mon Jan 21, 2008 10:57 pm Post subject: Re: Java TYS |
|
|
Have the parameter for .equals () set as an Object, and then typecast the parameter when checking for equality:
code: |
public boolean equals (Object otherFoo) {
return this.getName ().equals (((Foo)otherFoo).getName ());
}
|
I'm guessing HashMap will automatically typecast everything into Object before using the .equals () method. |
|
|
|
|
![](images/spacer.gif) |
Hikaru79
|
Posted: Mon Jan 21, 2008 11:00 pm Post subject: Re: Java TYS |
|
|
HellblazerX @ Mon Jan 21, 2008 11:57 pm wrote: Have the parameter for .equals () set as an Object, and then typecast the parameter when checking for equality:
code: |
public boolean equals (Object otherFoo) {
return this.getName ().equals (((Foo)otherFoo).getName ());
}
|
I'm guessing HashMap will automatically typecast everything into Object before using the .equals () method.
Excellent, except that your code would crash any time you tried to compare a Foo object to a non-Foo object (instead of just returning false). I'll just add the last piece:
Java: | return ((otherFoo instanceof Foo) && this.getName().equals (((Foo)otherFoo).getName())); |
+50 bits for you ![Wink Wink](http://compsci.ca/v3/images/smiles/icon_wink.gif) |
|
|
|
|
![](images/spacer.gif) |
Aziz
![](http://compsci.ca/v3/uploads/user_avatars/17740604804829f8242e90c.png)
|
Posted: Sat Feb 23, 2008 1:38 pm Post subject: RE:Java TYS |
|
|
Wow, such a little thing to over look, eh? That's why the @Override annotation was created! |
|
|
|
|
![](images/spacer.gif) |
|
|