Core Java Technologies Tech Tips Tips, Techniques, and Sample Code Welcome to the Core Java Technologies Tech Tips for October 21, 2003. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE). This issue covers: * Converting Between Old and New Collections * Choosers Outside Dialogs These tips were developed using Java 2 SDK, Standard Edition, v 1.4. This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of JZ Ventures, Inc. (http://www.jzventures.com). You can view this issue of the Tech Tips on the Web at http://java.sun.com/jdc/JDCTechTips/2003/tt1021.html. See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CONVERTING BETWEEN OLD AND NEW COLLECTIONS The introduction of the Java 2 Platform, Standard Edition version 1.2 offered a new standard library for dealing with collections of objects. That library is known as the Java Collections Framework. A base series of four interfaces and a set of about 20 support classes provide the whole framework. With some additions in the 1.4 release of the Java 2 Platform, Standard Edition, you get the current framework. People who use the framework frequently hear about the "old" and "new" collection classes. The old classes essentially define the original framework as released with version 1.0 of the Java platform. The classes are: o Vector o Hashtable o Enumeration The new framework did some retrofitting of the old classes so that they work in the new world, but it also added a new set of classes and interfaces that work well with the old set, but follow a new design model. The new interfaces are: o Set o List o Map o Iterator It's common when developing applications that you need to mix the old and new frameworks. Thankfully, when the new framework was developed, various support classes and methods were provided to simplify mixing the old and new frameworks. This tip describes various aspects of converting between the old and new frameworks. Converting From Legacy to New Collections The Vector and Hashtable classes are the main worker classes for collections in the old framework. Vector offers a dynamically resizable array, and Hashtable is a key-value lookup table. If you need to use implementations of these classes with the new framework, you can use them through the following new interfaces: List list = new Vector(); Map map = new Hashtable(); The important difference between using the old classes in this way, and the new implementations of the new interfaces, such as LinkedList, is that all the access methods of the data structure are synchronized in the legacy classes. Arrays are a core part of the Java programming language, and they haven't changed with the new framework. However, if you need to use them within the new framework, you can convert an array to a List with the asList method of Arrays: public static void main (String args[]) { List list = Arrays.asList(args); ... } In this way, you can readily use any array as part of the new collections framework. The Enumeration interface is what allows you to walk through the elements of a legacy collection. In the new framework, the Iterator interface is used for stepping through the elements. There is no built-in support for converting an Enumeration implementation to an Iterator. Typically, what you need to do is go back to the original collection and get an Iterator from there. You can do that in a way similar to the following: Old code: Vector v = new Vector(); ... Enumeration enum = v.elements(); New code: List list = new Vector(); ... Iterator iter = list.iterator(); Another option is to provide a simple Iterator implementation that does the Enumeration conversion for you. The following class maps the methods from the one interface into the other. In the case of the remove method of Iterator, there is no support. Notice that an UnsupportedOperationException is thrown there. import java.util.*; public class EnumerationIterator { public static Iterator iterator( final Enumeration enum) { return new Iterator() { public boolean hasNext() { return enum.hasMoreElements(); } public Object next() { return enum.nextElement(); } public void remove() { throw new UnsupportedOperationException(); } }; } public static void main (String args[]) { Vector v = new Vector(Arrays.asList(args)); Enumeration enum = v.elements(); Iterator itor = EnumerationIterator.iterator(enum); while (itor.hasNext()) { System.out.println(itor.next()); } } } The EnumerationIterator program: o Converts command line arguments to a Vector o Gets the vector's elements as an Enumeration o Converts that enumeration to an Iterator o Prints each element on its own line. If you run the program with the following command: java EnumerationIterator one two three you should see the the following output: one two three Converting From New to Legacy Collections The more interesting conversions are those that go from new to legacy collections. There are some third party libraries that still use the older collections classes. Because newer applications use the newer collections framework, you might need to retrofit some newer code to work in the older framework. The first of these new-to-legacy conversions involves going from newer collections to Vector and Hashtable. Here, the conversion is handled by requiring all implementations of the collection classes to provide a copy constructor. That means that you can pass any Collection into the Vector constructor, and get a second collection with the same set of elements. You can also pass a Map into the Hashtable constructor to get a Hashtable with an equivalent set of elements. Keep in mind that this is a shallow copy of the collection. Only the element references are copied into the new collection, not the objects themselves. For arrays, going from array to collection is easy, using the asList method of Array. Going from new collection to array is just as simple. Each of the collection implementations of the Set and List interfaces (the Collection implementations, not the Map implementations) provides two toArray methods for converting from Collection to an array: public Object[] toArray() Object[] toArray(Object type[]) By using either of these methods, you can get the current set of elements in the Collection as an array. The first toArray method creates a new Object array, sized to fit the number of elements in the collection. The second array method allows you to define what type of array to return. If sized correctly, the input array is also used as the value returned. However, if the size is too small, a new array of the argument type is returned. The following program, ArrayConv, illustrates how you might convert a String array to a List and then back to a String array. Notice that the array passed into toArray is sized exactly to the list's size. This eliminates the need to create a second array to return. Also notice that you must cast the returned array to the appropriate type. import java.util.*; public class ArrayConv { public static void main(String args[]) { List list = Arrays.asList(args); String newargs[] = (String[])list.toArray( new String[list.size()]); for (int i=0, n=newargs.length; i