This week's book giveaway is in the OCMJEA forum.
We're giving away four copies of OCM Java EE 6 Enterprise Architect Exam Guide and have Paul Allen & Joseph Bambara on-line!
See this thread for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes ClassCastException using Treemap.headMap() Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "ClassCastException using Treemap.headMap()" Watch "ClassCastException using Treemap.headMap()" New topic
Author

ClassCastException using Treemap.headMap()

O. Ziggy
Ranch Hand

Joined: Oct 02, 2005
Posts: 430

I am stuck with this problems



Output:


According to the API, Treemap.headMap() returns a SortedSet which suggests that a cast is not required? I cant work out what is the correct way to use the headMap() method.

Thanks in advance.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

O. Ziggy wrote:According to the API, Treemap.headMap() returns a SortedSet which suggests that a cast is not required? I cant work out what is the correct way to use the headMap() method.

If TreeMap.headMap() returns a SortedSet object, then the correct way to use it is to assign its result to a SortedSet variable.

Except when I look at the API it appears to return a SortedMap object. So your code should look like this:


Also I notice that at lines 27 and 31 of your posted code, you create a new object and assign it to a variable, only to immediately discard that object and assign a different object to that variable in the next line of code. Why are you doing that?
O. Ziggy
Ranch Hand

Joined: Oct 02, 2005
Posts: 430

Paul Clapham wrote:
Also I notice that at lines 27 and 31 of your posted code, you create a new object and assign it to a variable, only to immediately discard that object and assign a different object to that variable in the next line of code. Why are you doing that?


At lines 27 and 31, i am extracting the headSet from the TreeSet declared in line 05. The next line of code extracts the headMap from the TreeMap declared in line 16.

I was expecting that since headSet returns a TreeSet, headMap would return a TreeMap - see line 28.

Thanks
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

O. Ziggy wrote:
Paul Clapham wrote:
Also I notice that at lines 27 and 31 of your posted code, you create a new object and assign it to a variable, only to immediately discard that object and assign a different object to that variable in the next line of code. Why are you doing that?


At lines 27 and 31, i am extracting the headSet from the TreeSet declared in line 05. The next line of code extracts the headMap from the TreeMap declared in line 16.


No. At lines 27 and 31 you are creating an empty TreeSet and an empty TreeMap. It's lines 28 and 32 which actually extract data. They assign that data to the variables which used to point to the empty TreeSet and the empty TreeMap. In other words it was pointless to create those objects in the first place. So don't do that. It's wasteful, but more to the point it's confusing.
O. Ziggy
Ranch Hand

Joined: Oct 02, 2005
Posts: 430

Paul Clapham wrote:
O. Ziggy wrote:
Paul Clapham wrote:
Also I notice that at lines 27 and 31 of your posted code, you create a new object and assign it to a variable, only to immediately discard that object and assign a different object to that variable in the next line of code. Why are you doing that?


At lines 27 and 31, i am extracting the headSet from the TreeSet declared in line 05. The next line of code extracts the headMap from the TreeMap declared in line 16.


No. At lines 27 and 31 you are creating an empty TreeSet and an empty TreeMap. It's lines 28 and 32 which actually extract data. They assign that data to the variables which used to point to the empty TreeSet and the empty TreeMap. In other words it was pointless to create those objects in the first place. So don't do that. It's wasteful, but more to the point it's confusing.


I am not sure i understand what the alternative will be. The way i understood how it works is that headSet returns a new TreeSet. This is why i create a new TreeSet in line 27 and called it subset. This new Treeset will hold the result of calling the headSet method.

Do you mean i could have used a shorthand version? i.e. something like this



Sorry i didnt mean to confuse you even more..
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
You are still trying to cast to TreeMap. The return type of TreeMap.headMap is SortedMap. It is not the case that SortedMap IS-A TreeMap, so you can not cast it to TreeMap.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

O. Ziggy wrote:The way i understood how it works is that headSet returns a new TreeSet. This is why i create a new TreeSet in line 27 and called it subset. This new Treeset will hold the result of calling the headSet method.

Do you mean i could have used a shorthand version? i.e. something like this





Yes. Exactly. The headSet() method returns a TreeSet object. So it's pointless for you to create one. Just take the TreeSet object returned from headSet() and assign it to a variable of type TreeSet.

And no, that's not a "shorthand" version. That's the normal way of doing things. Your original version was the "unnecessary code" version.

John Stark
Ranch Hand

Joined: Jul 19, 2011
Posts: 185
The return type of TreeMap.headMap is SortedMap. It is not the case that SortedMap IS-A TreeMap, so you can not cast it to TreeMap.

Why does

work? The problem should be the same?

John
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
John Stark wrote:
The return type of TreeMap.headMap is SortedMap. It is not the case that SortedMap IS-A TreeMap, so you can not cast it to TreeMap.

Why does

work? The problem should be the same?

John


It should be the same, I agree, but thanks to the implementation details, it is not. The return type of TreeSet.headSet is SortedSet, but in the method implementation it is returning a TreeSet. So at runtime the cast works. The implementation of TreeMap.headMap returns a SubMap, a private inner class which is a sibling of TreeMap. So the cast fails. There's probably a good reason why it was implemented that way, but it's the kind of inconsistency that drives me mad.
John Stark
Ranch Hand

Joined: Jul 19, 2011
Posts: 185
Good to know, thanks. How do you know what the implementation is? The documentation does not tell you.

John
Pritish Chakraborty
Ranch Hand

Joined: Jun 12, 2012
Posts: 91

This thread is quite old, so I shouldn't be posting here, but since I was doing the topic I decided to contribute what little I know.

The newer Java 6 version of headMap() optionally takes boolean arguments in the form -:



The boolean arg specifies whether the subset starting(in this case, the end point of our SubMap) point is included or not.

If true, it is inclusive and false for exclusive. This form of headMap() returns a NavigableMap, which is what you probably could use alternatively.

If you don't include the boolean arg, the subset starting point is considered inclusive. In this form of the method, a SortedMap is returned, which is what you are getting here.


OCJP 6
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: ClassCastException using Treemap.headMap()