Tải bản đầy đủ (.pdf) (8 trang)

Compatibility Issues

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (16 KB, 8 trang )

Chapter 15: Compatibility Issues
There seems to have been great effort spent to ensure that the new Collections Framework works with the
historical collections. In this chapter, we'll examine the issues around conversion between the two, as well as
how to work with the framework in the older JDK 1.1 release. Lastly, we'll examine the differences within the
framework between the 1.2 and 1.3 releases of the Java 2 platform.
Converting from Historical to New Collections
The easiest conversions happen when going from the historical collection support into the new framework.
This would entail going from a Vector, Hashtable, array, or Enumeration into one of the new framework
pieces—or, more precisely, using one of the older implementations as a new implementation.
Vectors and Hashtables
Of the four conversions from historical to new collections, the simplest conversions are those involving
Vector and Hashtable. The designers of the new framework retrofitted these historical classes to be a part of
the new framework. The Vector class implements the List interface and acts like a presynchronized ArrayList.
The Hashtable implements the Map interface and acts like a presynchronized HashMap. Thus, if you need to
work with one of the older classes when a new implementation is needed, just pass along the older class and
you're done.
Note This automatic conversion from historical to new collections also holds true for the subclasses of Vector
and Hashtable: Stack and Properties, respectively.
Arrays
There are two different ways to work with arrays in the new framework. The Arrays class offers a series of
static methods to perform common functions like sorting and searching, as shown in Chapter 13. Using the
sorting and searching methods of the Arrays class isn't converting the array into something that is part of the
Collections Framework. In order to convert an array into something that is part of the framework, you need to
use the asList() method of Arrays:
public static void main (String args[]) {
List list = Arrays.asList(args);
}
When the array is converted by the asList() method, the created List is updateable with the changes reflected
in the original array. However, the list will not expand (or shrink) in size. If you try to add or remove an
element to or from the returned list, an UnsupportedOperationException will be thrown. In the case of
removal, the exception is thrown only if you try to remove something in the list. If the element isn't in the list,


the exception will not be thrown.
Enumerations
The final historical conversion is from an Enumeration into the new framework. You can work with an
Enumeration in the new framework in two different ways: you can use the Enumeration as an Iterator, or you
can create a collection with the Enumeration as the data source.
190
To use an Enumeration as an Iterator, you must create a wrapper, passing calls through the Iterator methods to
the Enumeration methods. The program in Listing 15−1 is one such wrapper.
Listing 15−1: Wrapping an Iterator around an Enumeration.
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());

}
}
}
As Enumeration doesn't support element removal, an UnsupportedOperationException will be thrown if
called.
The second method of using an Enumeration with the new framework is as the data source for a new
collection:
Enumeration enum = ...;
Set set = new HashSet();
while (e.hasMoreElements()) {
set.add(e.nextElement());
}
// use set
There is no magic here. Essentially, you just create the new collection instance and loop through the
enumeration adding one element at a time. More frequently than not, this construct is unnecessary. Usually,
you can return to the original data source of the enumeration and work with that source in a different manner
to make it a new collection type.
Chapter 15: Compatibility Issues
191
Converting from New to Historical Collections
The Collections Framework also includes support for backward compatibility. You can go from any collection
into a Vector, Hashtable, or array, or you can treat the collection as an Enumeration.
Vectors and Hashtables
For the Vector and Hashtable classes, the conversion is handled by requiring collection implementation
classes to have a copy constructor. Since Vector has been retrofitted into the framework, it has a constructor
that accepts any Collection object: Vector (Collection c). In the case of Hashtable, it now has a constructor
that accepts a Map: Hashtable(Map m). By using these new constructors, you can easily convert a new
collection into an old collection.
Arrays
As far as arrays go, the Collection interface includes the toArray() method to convert a new collection into an

array. There are two forms of this method. The no argument version will return the elements of the collection
in an Object array: public Object[] toArray(). The returned array cannot be cast to any other data type. This is
the simplest version and in most cases sufficient. The second version requires you to pass in the data type of
the array you'd like returned: public Object[] toArray(Object type[]). If the array passed into this version isn't
large enough, a new array will be created of the appropriate type. With this second version, you can cast the
returned array to the type passed into the toArray() method. For instance, assuming col represents a collection
of Date objects, the following line would succeed:
Date stuff[] = (Date[])col.toArray(new Date[0]);
Note In the event that the elements of the collection are not type−compatible with the desired array type, an
ArrayStoreException will be thrown when toArray() is called.
In working with Map collections as an array, you'll need to get either the collection of entries, the keys, or the
values for the map and convert that into an array as shown here:
String keys[] = (String[])map.keySet().toArray(new String[0]);
There are no direct map−to−array conversions available.
Enumerations
The final conversion occurs in going from a Collection to an Enumeration. There is a helper method in the
Collections class that does the conversion for us: Enumeration enumeration(Collection). Given any
Collection, the enumeration() method will convert it into an Enumeration:
List l = Arrays.asList(args);
Enumeration enum = Collections.enumeration(l);
As with the toArray() method, if you'd like to convert a Map to an Enumeration, you need to work with the
map's specific set of entries, keys, or values:
Enumeration enum = Collections.enumeration(map.entrySet());
Converting from New to Historical Collections
192
Working with JDK 1.1
To help developers transition their older programs to the Java 2 platform, the designers of the Collections
Framework developed a partial backport that would run with the 1.1 release of Java. The classes are
essentially source code−equivalent to those delivered with the 1.2 version of Java but include everything in
the com.sun.java.util.collections package instead of java.util. The reason for the package difference is that

browsers can't download classes in the java.* packages, so the classes needed to move elsewhere.
To get the backport, go to the InfoBus homepage
The reason for this location is that the
backport package was created so InfoBus could run in a Java 1.1 environment. It's available for everyone to
use. Once downloaded, unzip the file and add the collections.jar file in the lib directory to your CLASSPATH.
Note InfoBus is a communications scheme developed by Lotus/IBM for sending messages
between JavaBean components. While I have nothing against InfoBus, its usage seems to be
dropping in favor of the Java 2 Enterprise Edition (J2EE) standard Java Message Service
(JMS) API.
The backport of the framework only includes all the new classes introduced with the Collections Framework.
Any java.lang class like String that was updated for the Java 2 platform to be compatible with the framework
has not been updated, as you can't randomly replace system classes. This means that classes like Vector and
Hashtable have been modified to be part of the framework but what you put into the collections has not. Table
15−1 provides a list of the newly available classes.
Table 15−1: Classes in Collections Backport
NAME
AbstractCollection Iterator
AbstractList LinkedList
AbstractMap List
AbstractSequentialList ListIterator
AbstractSet Map
ArrayList NoSuchElementException
Arrays Random
Collection Set
Collections SortedMap
Comparable SortedSet
Comparator TreeMap
ConcurrentModificationException TreeSet
HashMap UnsupportedOperationException
HashSet Vector

Hashtable
Warning There is a hidden trap in using the backport: you cannot cast (explicitly or implicitly) a Vector to a
Vector if one Vector is in java.util while the other is in com.sun.java.util.collections. This can show
up when one developer writes a class with a method that takes a java.util.Vector and another calls it
Working with JDK 1.1
193
from a class that is using the collections backport and is including
com.sun.java.util.collections.Vector. The compiler will spot this, but it may be a little confusing the
first time a developer gets this error message!
Comparing Objects with JDK 1.1
When comparing system classes for tasks like sorting with the Java 2 platform, you can rely on the fact that
many of these core classes implement the Comparable interface. Unfortunately, when using the 1.1 backport,
you cannot rely on this. Not only are the classes not comparable, but when you need ordering, you must
provide your own Comparator.
While the JDK 1.1 compiler will let you pass arrays or collections of anything to the sorting routines of the
Arrays and Collections classes, if you were to pass any of the system classes that are Comparable in the Java 2
platform but aren't in JDK 1.1, you would get a ClassCastException thrown at runtime. In addition, the
Collections class offers a reverse order Comparator from its reverseOrder() method. This too is not usable in
JDK 1.1 with the system classes as it relies on the natural ordering of the classes (they must implement
Comparable). Since the system classes don't have a natural order in JDK 1.1, using the reversing comparator
with the system classes will result in a ClassCastException being thrown, too.
In order to sort system classes in JDK 1.1 properly, you must define a custom Comparator and provide a
public int compare(Object o1, Object o2) method to order two elements of the appropriate type. If you have
trouble figuring out how to properly sort the different classes, a good place to look is in the compareTo()
methods of the 1.2 and 1.3 versions of the classes. To help, the utility class in Listing 15−2 provides a
Comparator for each of the String, Integer, and Date classes.
Listing 15−2: String, Integer, and Date comparators for JDK 1.1.
import com.sun.java.util.collections.*;
import java.util.Date;
public class Comparators {

public static Comparator stringComparator() {
return new Comparator() {
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
int len1 = s1.length();
int len2 = s2.length();
int n = Math.min(len1, len2);
char v1[] = s1.toCharArray();
char v2[] = s2.toCharArray();
int pos = 0;
while (n− != 0) {
char c1 = v1[pos];
char c2 = v2[pos];
if (c1 != c2) {
return c1 − c2;
}
pos++;
}
return len1 − len2;
}
};
}
Comparing Objects with JDK 1.1
194

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×