• Post Reply Bookmark Topic Watch Topic
  • New Topic

TreeMap - Can't understand the output.  RSS feed

 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I have a class (MyClass) that implements Cloneable interface and has two instant fields.

String drink
int a

Besides the setters/getters/constructors, this class also overrides the following methods from the Object class.



My comparator is as follows.



Here is the file that contains the main method.



When I execute this code, I get the following output.

null null
null null
( a= 10, drink = EnglishCoffee ) VALUE2
( a= 16, drink = GreenTea ) VALUE2
( a= 25, drink = EnglishCoffee ) null

Following are the records in order that I tried to put in the TreeMap.


MyClass MyValues
a drink

1 25 EnglishCoffee VALUE1
2 10 EnglishCoffee VALUE2
3 10 EnglishCoffee VALUE1
4 16 GreenTea VALUE2
5 10 Latte VALUE2
6 null VALUE1
7 25 Latee NULL
8 NULL NULL

Based on the records I tried to put in the TreeMap and what the iterator shows me, it looks like the TreeMap does not use equals method at all to place the elements in it or to check for equality while placing an element in the map. Would that be correct?

I got the same output even after commenting out the equals method which is why it seems so. Does it only use the comparator?
Further I've read that the TreeMap allows for only one null key to be there in the data structure. But my comparator has a logic to deal with nulls differently. So does the treatment of null keys depend on the Comparator solely?

If I try to dry run my code based on the comparator, it seems like the following is what is happening.

1. Record 1 gets in. So we get 25, EnglishCoffee, Value1
2. Comparator returns a -1. Record gets in. We get 10, EnglishCoffee, Value2
3. For the record 3, the comparator returns a 0. Does it update the key and value? It seems like it updates only the value, not the key. Would that be correct? We get 10, EnglishCoffee, Value1
4. Record 4 gets in cause the comparator returns a 1. We get 16, GreenTea, Value2
5. Record 5 overwrites the value of 10, EnglishCoffee again. We get 10, EnglishCoffee, Value2
6. Null key gets the comparator to return a -1. We get null, Value1
7. This record is the same as root. So it updates roots value. We get 25, EnglishCoffee, Null
8. This record meets the first if in the comparator. We get a -1. We get Null, Null.

So I should get
Null, Null
Null, Value1
( a= 10, drink = EnglishCoffee ) VALUE2
( a= 16, drink = GreenTea ) VALUE2
( a= 25, drink = EnglishCoffee ) null

But I am getting
null null
null null
( a= 10, drink = EnglishCoffee ) VALUE2
( a= 16, drink = GreenTea ) VALUE2
( a= 25, drink = EnglishCoffee ) null

I am not sure, if my dry run steps are correct. Could you please help me figure them out.

Thanks,
Chan.



 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, so after a lot of reading and lot of trying out the various combinations of compare method ( along with equals and hashcode ), I have sort of figured this. The reason I'm getting a null for null key is "probably" because even before get(key) does a lookup for value, it probably also does a key lookup in map and that fails because of the following lines in the compare method.

if (a==null) return -1;
else if ( b==null) return 1;

I get the value as null even if I comment out the last line in the following code.



There is a lot more to read on why it is such a bad idea to have equals out of sink with compare but looks like it is going to be interesting ( At least that is what I keep telling myself) and which methods invoke equals and which ones invoke compare to test for equality.

After adding following to the code-


I got the following output.

null null
null null
( a= 10, drink = EnglishCoffee ) VALUE2
( a= 16, drink = GreenTea ) VALUE2
( a= 25, drink = EnglishCoffee ) VALUE2
{null=null, null=VALUE1, ( a= 10, drink = EnglishCoffee )=VALUE2, ( a= 16, drink = GreenTea )=VALUE2, ( a= 25, drink = EnglishCoffee )=VALUE2}

and that shows that there is a null key with VALUE1 in the map. Just get(null) cannot find it.





 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!