Sunday, 13 March 2011

Compatibility in collections

The Collection Framework was designed to ensure complete interoperability between the new collection interfaces and the types that have traditionally been used to represent collections: Vector(in the API reference documentation), Hashtable(in the API reference documentation), array, and Enumeration(in the API reference documentation). In this section, you'll learn how to transform traditional collections to new collections and vice-versa.

Upward Compatibility

Suppose that you're using an API that returns traditional collections in tandem with another API that requires objects implementing the collection interfaces introduced in JDK 1.2. To make the two APIs interoperate smoothly, you'll have to transform the traditional collections into new collections. Luckily, the Collection Framework makes this easy. Suppose that the old API returns an array of objects, and the new API requires a Collection. As discussed in the implementations lesson, the collections framework has a convenience implementation that allows an array of objects to be viewed as a List. Using Arrays.asList(in the API reference documentation), an array can be passed to any method requiring a Collection or a List:
Foo[] result = oldMethod(arg);
newMethod(Arrays.asList(result));
If the old API returns a Vector or Hashtable you have no work to do at all, since Vector has been retrofitted to implement the List interface, and Hashtable has been retrofitted to implement Map. Thus, a Vector may be passed directly to any method calling for a Collection or a List:
Vector result = oldMethod(arg);
newMethod(result);
Similarly, a Hashtable may be passed directly to any method calling for a Map:
Hashtable result = oldMethod(arg);
newMethod(result);
Less frequently, an API may return an Enumeration that represents a collection of objects. While there is no direct support for translating an Enumeration into a Collection, it's a simple matter to create a Collection containing all the elements returned by an Enumeration:
Enumeration e = oldMethod(arg);
List l = new ArrayList();
while (e.hasMoreElements())
l.add(e.nextElement());
newMethod(l);

Backward Compatibility

Suppose you're using an API that returns "new collections" in tandem with another API that requires you to pass in "traditional collections". To make the two APIs interoperate smoothly, you have to transform the new collections into traditional collections. Again, the Collection Framework makes this easy. Gosh, isn't this your lucky day? Suppose that the new API returns a Collection, and the old API requires an array of Object. As you're probably aware, the Collection interface contains a toArray method, designed expressly for this situation:
Collection c = newMethod();
oldMethod(c.toArray());
What if the old API requires an array of String (or some other type) instead of an array of Object? All hope is not lost. You just use the other form of toArray, the one that takes an array on input:
Collection c = newMethod();
oldMethod((String[]) c.toArray(new String[0]));
If the old API requires a Vector, the standard collection constructor comes in handy:
Collection c = newMethod();
oldMethod(new Vector(c));
The case where the old API requires a Hashtable is handled analogously:
Map m = newMethod();
oldMethod(new Hashtable(m));
Finally, what do you do if the old API requires an Enumeration? This case isn't common, but it does happen from time to time, and the Collections.enumeration(in the API reference documentation)method was provided to handle it. This method is a static factory that takes a Collection and returns an Enumeration over the elements of the Collection:
Collection c = newMethod();
oldMethod(Collections.enumeration(c));

No comments:

Post a Comment