Question

Say I've intialized a Set as a new TreeSet:

    Set<Integer> foo = new TreeSet<Integer>();

And I want to use the .pollFirst() method, because I'm lazy and I don't want to have to use a temp variable because I have this handy method that would reduce what would otherwise be 3-4 lines of code to 1 line.

However, with the following code, the only way to compile my code would be to specifically call foo a TreeSet.

    while (foo.size() > 1) {
        int lower = foo.pollFirst();
        int higher = foo.pollFirst();
        foo.add(higher - lower);
    }

So why java doesn't realize that foo is actually a TreeSet? Should I just cast it as TreeSet if I didn't want to intialize foo as a TreeSet? Or would it be better to just intialize it that way?

Further Testing with Casting:

    while (foo.size() > 1) {
        int lower = (int) ((TreeSet) foo).pollFirst();
        int higher = (int) ((TreeSet) foo).pollFirst();
        foo.add(higher - lower);
    }

This makes it compile without explicitly calling it a TreeSet upon intialization.

Was it helpful?

Solution

That's because Set doesn't define a pollFirst() method, it is defined by NavigableSet, which is implemented by TreeSet. On the other hand, to answer your question, one good reason I can think of for java to behave like that, is this, assume that later in your code you do something like this,

Set<Integer> foo = new TreeSet<Integer>();
...
foo = ExternalLibraryClass.getUnknownSetImplementation();
// At this point, how would the compiler know what 'foo' actually is?

where ExternalLibraryClass is an arbitrary class from an arbitrary library and getUnknownSetImplementation() is an arbitrary method that returns a Set implementation. The important thing is that your compiler does NOT have access to the library's source code, therefore it does NOT know what Set implementation will be returned every time getUnknownSetImplementation() gets called.

SOME MORE ILLUSTRATION

Assume,

String whichSet = externalWebService.whichSetShouldIUse();
if(whichSet.equals("HashSet"))
  foo = new HashSet()<>;
else if(whichSet.equals("TreeSet"))
  foo = new TreeSet()<>;

// At this point, how would the compiler know what 'foo' actually is?

OTHER TIPS

The Short Answer

This is because that Set doesn't define the pollFirst() or pollLast() methods. You may check the Set Interface documentation here and the TreeSet Class documentation here to verify this.

The Long Answer

The reason why this happens is because of Inheritance. The child class inherits members from the parent class, but the parent class won't have any idea of its children's members. Now in the Collection framework in Java, the Set interface is the parent of the TreeSet class.

As a result, when we use a Set reference to initialize a TreeSet object, we miss out on the member functions specifically written for TreeSet (which is pollFirst() in your case). However common member functions(first(), last()) to both of them work fine without any issues.

Example

In the examples here and here TreeSet reference is used for declaration, thus it works without any problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top