A common need for all but the most trivial of Java applications is the ability to gather together a collection of object references. Java has always had minimal support for object collections, with the Vector, Stack and Hashtable classes. There is also, of course, the handy array of objects (though the array is fixed in size). The Java 2 platform takes this one step further, by providing a common framework for representing object collections, as well as some concrete implementations of data structures. The Java collections framework is a set of interfaces and classes that provide an easy way to store collections of objects.
Why introduce a new API just for data structures?
The data structures provided by earlier editions of the Java platform are primitive tools for serious application development. For example, adding and deleting from an array requires reshuffling, and extra code has to be added for sorting. While a class like Vector helps with resizing, it still doesn't guarantee order. That means extra work for developers, every time they want to use it. Wouldn't it be nice if you didn't care about the implementation of the data structure, and could just use it?
That's what the collections framework provides. It introduces a variety of interfaces and classes, which belong to two distinct groups (Collection and Map). Collections are for storing a sequence of object references, whereas Maps provide a key-value pair mapping to objects. Together with some support classes, the collection framework offers developers the following benefits:
A wider variety of data structures, for those who don't want to write their own
A standard framework for developing new data structures that are interoperable
Easy-to-use interfaces, with implementations that can be transparently substituted to improve application performance.
This new framework adds a new degree of maturity to the Java programming language, by providing a more-useful data structure API consistent with the flexibility and versatility of other parts of the Java API.
interface provides a base from which other collection interfaces are extended. It declares several methods, which provide the means by which object references can be added to a collection, searched, accessed, and removed.
Adds the specified object
Adds all of the objects contained in the specified collection
Dumps all stored objects
boolean contains (Object o)
Checks for presence of specified object
boolean containsAll (Collection)
Checks for presence of all objects contained in the specified collection
boolean isEmpty ()
Checks for an empty collection
Iterator iterator ()
- a sequence of data elements
remove (Object o)
Removes the specified object
Removes all objects contained in the specified collection
Removes all objects not contained in the specified collection
Returns the number of elements in the collection
Object toArray ()
Converts the collection to an array
interface offers a standard set of methods, regardless of the actual type of collection that is used. Indeed, in many situations the actual data structure used will be irrelevant to the code, and could be easily substituted (perhaps for performance reasons). By referring to the data structure as a
instance, and not its class, you can substitute it at a later date without requiring any further code changes.
c = new ArrayList(); OR
c = new LinkedList();
// Add elements to the collection
c.add ( ... );
The collections framework also makes an important distinction between types of collections, by offering a further two new interfaces. A
is a collection that accepts only one copy of an object, whereas a
can accept multiple copies. Figure One shows the relationship between the
Figure 1. Collection interfaces.
More often than not, programmers will be using implementations of the
interface, which corresponds to the old
class. In fact, the
class has been modified to make it compatible with the new
interface. Also, there is another interface (
) which imposes a further condition that a
be sorted. When writing data structure implementations, these interfaces will be very useful (and corresponding
templates are also provided). However, in normal circumstances, developers will choose existing implementations provided as part of the collections framework.
interface declares methods for classes that implement a mapping between keys and values. While part of the collections framework, it does not subclass the
interface it is for representing mappings not aggregations.
implementations are subject to a few restrictions:
Each key maps to a single
(though this object can itself be a
Each key is unique.
If these restrictions sound extreme, remember that multiple values can be achieved by storing a
rather than an
. Maps are extremely useful, and even before their introduction in JDK 1.2, were quite commonplace. The
class is a
that most developers will be familiar with, and it has been modified in JDK 1.2 to implement the
interface. The following table shows the most useful methods of the
Dumps all stored objects
boolean containsKey (Object)
Checks for the presence of a key
boolean containsValue (Object)
Checks for the presence of a value
Set entrySet ()
collection of key-value mappings represented as
boolean equals (Object)
Checks for equality between two maps
Object get (Object)
Returns the value associates with the specified key, and
if no such mapping exists, or if the key is mapped to the
boolean isEmpty ()
Checks for an empty map
collection of all keys
Object put (Object key, Object value)
Maps the key to the specified value, overwriting any previous mapping for that key. Returns the previous mapping (which may be
Object putAll (Map)
Puts all key-value pair mappings in the specified map into the current map. Similiar to the
remove (Object o)
Removes specified object
Returns number of elements in collection
As in the
interface provides a standard set of methods that can be used with Maps. By maintaining reference to the
interface, and not
implementations, it is easy to later substitute an alternate data structure. Also, the
interface is similar to the older JDK 1.0
abstract class. When designing new implementations, the
interface should be used in place of the
class. This means implementing the
interface, instead of extending the
// Old way of creating a map-like data structure public class FileBasedHashTable extends java.util.Dictionary
// New way of creating a map-like data structure public class FileBasedHashtable implements java.util.Map
There is also a
interface, which provides a method for sorting the key mappings. When using a
, all keys must implement the new
interface, which is required to allow comparison during the sorting process. The good news is that most of the wrapper objects for primitive data-types (
Byte, Character, Double, Float,
, etc.) implement the
interface, but when using custom-designed classes as keys, you will need to implement
, or avoid using a
With the new collections framework included in the Java 2 platform, developers finally have at their fingertips a good suite of data structure implementations and interfaces from which further classes can be built. In the next part of our lesson (The Java Collections Framework: Implementations), we'll examine the new classes that form the collections framework, such as linked lists and trees. We'll also look at how you can safely use collections in a multithreaded environment and how to convert from a
David Reilly is a software engineer and freelance technical writer living in Australia. A Sun Certified Java 1.1 Programmer, his research interests include the Java programming language, as well as networking and distributed systems. He can be reached via e-mail at firstname.lastname@example.org, or via his personal Web site.
Enterprise Development Update
Don't miss an article. Subscribe to our newsletter below.