This question relates to Java collections - specifically Hashtable and Vector - but may also apply elsewhere.
I've read in many places how good it is to program to interfaces and I agree 100%. The ability to program to a List interface, for instance, without regard for the underlying implementation is most certainly helpful for decoupling and testing purposes. With collections, I can see how an ArrayList and a LinkedList are applicable under different circumestances, given the differences with respect to internal storage structure, random access times, etc. Yet, these two implementations can be used under the same interface...which is great.
What I can't seem to place is how certain synchronized implementations (in particular Hashtable and Vector) fit in with these interfaces. To me, they don't seem to fit the model. Most of the underlying data structure implementations seem to vary in how the data is stored (LinkedList, Array, sorted tree, etc.), whereas synchronization deals with conditions (locking conditions) under which the data may be accessed. Let's look at an example where a method returns a Map collection:
public Map<String, String> getSomeData();
Let's assume that the application is not concerned at all with concurrency. In this case, we operate on whatever implementation the method returns via the interface...Everybody is happy. The world is stable.
However, what if the application now requires attention on the concurrency front? We now cannot operate without regard for the underlying implementation - Hashtable would be fine, but other implementations must be catered for. Let's consider 3 scenarios:
1) Enforce synchronization using synchronization blocks, etc. when adding/removing with the collection. Wouldn't this, however, be overkill in the event that a synchronized implementation (Hashtable) gets returned?
2) Change the method signature to return Hashtable. This, however, tightly binds us to the Hashtable implementation, and as a result, the advantages of programming to an interface are thrown out the window.
3) Make use of the concurrent package and change the method signature to return an implementation of the ConcurrentMap interface. To me, this seems like the way forward.
Essentially, it just seems like certain synchronized implementations are a bit of a misfit within the collections framework in that, when programming to interfaces, the synchronization issue almost forces one to think about the underlying implementation.
Am I completely missing the point here?
Thanks.