4

Ok so SortedMap / SortedSet is an interface, and TreeMap / TreeSet is it's implementation. Both of them keep the elements in sorted order, right? So why do we need TreeMap / TreeSet?

user2027425
  • 389
  • 3
  • 5
  • 14

5 Answers5

13

Interfaces do not provide any functionality, they just define the general outline of a class in terms of the methods it provides. But there's no code inside SortedMap/SortedSet that implements how to actually achieve this functionality.

And as a matter of fact, you can often have multiple ways to realize the same functionality. Think of the interface java.util.Set: you could implement it as a TreeSet but also as a HashSet. Usually, there are some trade-offs between different implementations: a hashset might provide faster access times on average, while a tree set may be better at keeping the order of its items.

Often enough, however, a developer doesn't really care about the implementation details, as long as they know that they can store items in a set and retrieve them. That basic idea, but not how to achieve it, is defined by the interface.

This is also the reason you cannot instantiate an interface. If you try the following:

SortedSet<Integer> set = new SortedSet<Integer>();

your compiler will complain. That is because "SortedSet" does not really realize a set itself, it just defines what an implementation of a sorted set must provide in terms of methods.

Here's a contrived example. Imagine you want to offer a functionality to compute the percentage of positive integers in a set. You could define a method:

public double getPercentageOfPositives(Set<Integer> set) {
    if (set.size() == 0) {
        return 0.0;
    }

    int count = 0;

    for (Iterator<Integer> iter = set.iterator(); iter.hasNext();) {
        if (iter.next() > 0) count++;
    }

    return 100.0 * count / set.size();
}

Here, you don't really care whether the user of your method gives you a TreeSet or a HashSet. It doesn't matter which principle the given class uses, because you're just calling the size() method and the iterator() method anyway. All you need is trust in the fact that any set will have these two methods. An interface gives you that trust.

Therefore your method signature only asks for a Set, which is an interface that defines that all classes implementing it must provide (amongst others) a size() and an iterator() method. If you wrote it like this:

public double getPercentageOfPositives(SortedSet<Integer> set) {
    ...
}

and I have an instance of HashSet then I couldn't use your method even though HashSet provides size() and iterator() as well. :-(

In that sense, an interface is like a super-class, it defines the commonalities that all classes must have that implement it. But it does not provide any functionality itself.

Thus to come back to your original example of SortedSet: this interface does not provide any functionality. It merely defines which methods a sorted set implementation must provide. TreeSet is such an implementation.

The same line of thought applies to SortedMap.

Thomas
  • 17,016
  • 4
  • 46
  • 70
  • So are these legal: `SortedSet set = new TreeSet();` `Set set = new SortedSet();` `SortedSet set = new HashSet();` – user2027425 Feb 07 '13 at 05:30
  • 1
    No. The second one is not legal because `SortedSet` is an interface and not a class, so you cannot instantiate it with `new`. See the example above -- it doesn't matter what's to the left of the `=` sign. The third one does not work because `HashSet` does not *implement* `SortedSet`. You can see that in the documentation of `HashSet`. It does however implement `Set`, so the following works: `Set set = new HashSet();`. – Thomas Feb 07 '13 at 05:40
  • Okay. So basically, what's on the right on the `=` must be a class, and on the left, it can be a class or an interface. – user2027425 Feb 07 '13 at 05:43
  • That's right. If the left-hand side is an interface, then the class on the right-hand side must implement it. If the left-hand side is a class, then the class on the right-hand side must be the same or a sub-class of it. – Thomas Feb 07 '13 at 05:50
  • 1
    There's also *abstract classes* which are something like a hybrid between an interface and a class implementing the interface: they provide a little bit of implementation, but also have some un-implemented methods (like an interface) for sub-classes to implement. Therefore you cannot instantiate abstract classes either. A common pattern you often see is an interface, implemented partly by an abstract class, sub-classed by a concrete class. But don't worry if it's getting a bit too much at this point, it'll all fall into place as you move along. – Thomas Feb 07 '13 at 05:52
4

Right because we need interfaces when we have classes.

SortedMap and SortedSet define functionality which is implemented by using trees with a TreeMap and a TreeSet.

Jack
  • 131,802
  • 30
  • 241
  • 343
2

SortedMap/SortedSet are interfaces, so you cannot instantiate them. TreeMap/TreeSet are classes and can be instantiated and used. The reason why do we need SortedMap/SortedSet is that there could be implementations other than Sun's tree-based ones.

Mikhail Vladimirov
  • 13,572
  • 1
  • 38
  • 40
2

Here is a cheat sheet to get the big picture (Source is in the image)

enter image description here

TastyCode
  • 5,679
  • 4
  • 37
  • 42
0

The answer is in your question; SortedMap and SortedSet are interfaces. They define methods and properties, but they don't actually implement them, so they don't provide any functionality.

TreeMap and TreeSet are implementations of these interfaces.

Good OOP design practices recommend that you code to interfaces, not implementations. That means that all of your method signatures should refer to interfaces and not classes.

So you would do:

Object squishObjects(SortedMap map);

instead of

Object squishObjects(TreeMap map);

That way, if a better implementation of SortedMap comes along, you can switch that in, without having to modify all of your methods that relied on TreeMap.

Dancrumb
  • 26,597
  • 10
  • 74
  • 130