Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

TreeSet adding twice null

 
Anton Brass
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I found a question at Nikos Blog, where adding twice null to a TreeSet ends up in an Exception, altough adding it once is fine. Why?



I think I also saw once that adding null to a TreeSet that already have items ends up also in an exception.
Is it possible to add null after "anything" was added? I guess not since it is natural ordering or?

The API isn't really clear about that fact:

[...]
More formally, adds the specified element e to this set if the set contains no element e2 such that (e==null ? e2==null : e.equals(e2))
[...]

Throws
ClassCastException - if the specified object cannot be compared with the elements currently in this set
NullPointerException - if the specified element is null and this set uses natural ordering, or its comparator does not permit null elements
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You have found a java bug
 
Seetharaman Venkatasamy
Ranch Hand
Posts: 5575
Eclipse IDE Java Windows XP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
TreeSet is backed by TreeMap . I would suggest you to go through the add method of TreeSet or put method of TreeMap.
 
Anton Brass
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
well I reviewed the API of TreeSet and don't understand it clear enough

Is it really a bug?

What is the expected behavior, never accept a null or? The Problem is, if you put in a null before any object is inside the TreeSet, how the JVM should know if the Comparator that is used in the future (or maybe never) is allowing null or not?
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Internally the TreeSet uses a TreeMap. And the TreeSet.add() delegates it to TreeMap.put(). Just open the source of that method and you'll see the bug. There is even a comment about the bug.
 
Shanky Sohar
Ranch Hand
Posts: 1051
Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i run this code on jdk6.0 and it is giving me error.
Could you please tell which jdk you are using
 
Huachaitou Peek
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wouter Oet wrote:Internally the TreeSet uses a TreeMap. And the TreeSet.add() delegates it to TreeMap.put(). Just open the source of that method and you'll see the bug. There is even a comment about the bug.



How can I take a look at source code ? Is there an easy way to do that ? Thanks.
 
Steli Niculescu
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Huachaitou Peek wrote:
Wouter Oet wrote:Internally the TreeSet uses a TreeMap. And the TreeSet.add() delegates it to TreeMap.put(). Just open the source of that method and you'll see the bug. There is even a comment about the bug.



How can I take a look at source code ? Is there an easy way to do that ? Thanks.

http://lmgtfy.com/?q=TreeSet+docjar&l=1
 
Harpreet Singh janda
Ranch Hand
Posts: 317
Eclipse IDE
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This exception is due to the fact that the TreeSet maintains the order of the elements added. Whenever we add an element to the TreeSet it compare the added element with already existing elements to find the correct position of the newly added element.

So if the TreeSet will be empty the first element will be directly added to the TreeSet as there are no elements to be compared.
But if there is any element in the TreeSet, it will through a null pointer exception when newly added element will be compared with the already existing elements (as any operation on a null object throw null pointer exception).
 
Anton Brass
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok thanks, anyway shitty behavior ;)
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Huachaitou Peek wrote:How can I take a look at source code ? Is there an easy way to do that ? Thanks.

In your java distribution the is a src.zip. Just unzip it and you have the source code.

Harpreet Singh janda wrote:This exception is due to the fact that the TreeSet maintains the order of the elements added. Whenever we add an element to the TreeSet it compare the added element with already existing elements to find the correct position of the newly added element.

So if the TreeSet will be empty the first element will be directly added to the TreeSet as there are no elements to be compared.
But if there is any element in the TreeSet, it will through a null pointer exception when newly added element will be compared with the already existing elements (as any operation on a null object throw null pointer exception).
Although that sounds like a plausible answer and matches with the external behavior, it's not what happens internally.

First of all we're not using a custom comparator thus the natural order is maintained. If you would have provided a custom comparator then the nullpointer will probably occur there.
Internally the TreeSet uses a TreeMap. When you add the first element to it there are no conditions to be met. The key may be null. But when another element is added the code checks for null and in case the key is null then a nullpointer exception is thrown.

So:
add(null); add(null); throws NullPointerException because of the null check
add(null); add("JavaRanch"); throws NullPointerException because the String comparable uses a method of the null value
 
Harpreet Singh janda
Ranch Hand
Posts: 317
Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It does not matter whether we are using a custom comparator or the one provide by the java itself. If we are not providing a custom comparator then the comparator provided by the java itself will be used (To maintain the natural order).

So whenever we try to ad a null it will throw a NPE because internally the null will be compared with the other values (by custom of the core comparator) and any operation on null produces the NPE.
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Harpreet Singh janda wrote:It does not matter whether we are using a custom comparator or the one provide by the java itself.
Actually it does. This runs without exceptions:
TreeMap doesn't enforce that the key can't be null if a custom comparator is provided.
 
Harpreet Singh janda
Ranch Hand
Posts: 317
Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That means NPE is due to the comparator not the internal structure of TreeSet.
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Harpreet Singh janda wrote:That means NPE is due to the comparator not the internal structure of TreeSet.

That is exactly what I said:
Wouter Oet wrote:So:
add(null); add(null); throws NullPointerException because of the null check
add(null); add("JavaRanch"); throws NullPointerException because the String comparable uses a method of the null value
 
Harpreet Singh janda
Ranch Hand
Posts: 317
Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So both of us are no the same page
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic