Published: May 21, 2001
By Richard G. Baldwin
Java Programming, Lecture Notes # 1354
The purpose of this miniseries is to help you learn the essential features of Object-Oriented data structures in Java using the Collections Framework.
You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth to view the listings while you are reading about them.
I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find those lessons published at Gamelan.com. However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there. You will find a consolidated index at Baldwin's Java Programming Tutorials.
The index on my site provides links to the lessons at Gamelan.com.
So, just what is the purpose of this set of core interfaces? Hopefully, the following paragraphs will answer that question.
A collection is an object of some type, and that type is defined in a generic sense by one or more interfaces that make up the Collections Framework.
What is a data type?
All data types specify the operations that can be performed on an entity of that type. (Data types also specify the kinds of data that can be stored in an entity of that type, but that is not germane to this discussion.)
Interface is a type
An object in Java can often be considered to be of several different types. One of those types is determined by any interfaces implemented by the class from which the object was instantiated. Framework collection objects in Java are instantiated from classes that implement the core interfaces of the framework.
Thus, a Java interface in the Collections Framework specifies the type of such an object, and provides a generic representation of the operations that apply across different implementations of the interface.
Collection interface declares several methods
The Collection interface declares several methods. This is not unusual. From a technical standpoint, all interfaces declare none, one, or more methods. Most interfaces declare several methods. (Interfaces can also declare constants, but that is not germane to this discussion.)
In general, there is no technical requirement for a specification of the behavior of the interface methods when implemented in a class. In fact, because a method that is declared in an interface is abstract, it specifically refrains from defining the behavior of the method. The interface definition simply declares the interfaces for all the methods that it declares.
An extra step
The Sun documentation for the Collection interface, however, goes a step beyond the minimum technical requirements for an interface. The documentation describes the general behavior that must be exhibited by each of the methods belonging to an object instantiated from a class that implements the Collection interface. This is sometimes referred to as a contract.
Therefore, if you define a class that implements the Collection interface in a manner consistent with the Collections Framework, it is important that you make certain that each of your methods behaves as described in the Sun documentation. In other words, you must be careful to comply with the contract defined for those methods. If you don't do that, a user can't rely on objects instantiated from your class exhibiting proper behavior.
The add() method in Collection
For example, the Collection interface declares a method named add(), which receives an incoming reference of type Object, and returns a boolean. Here is one of the paragraphs from the Sun JDK 1.3 documentation describing the required behavior (contract) of the add() method for any class that implements the Collection interface.
"Ensures that this collection contains the specified element (optional operation). Returns true if this collection changed as a result of the call. (Returns false if this collection does not permit duplicates and already contains the specified element.)"
As you can see, the behavior is defined in a very general way. There is no indication as to how that behavior is to be achieved. (In addition, the documentation provides several other paragraphs describing the contract for the add() method.)
The add() method in Set
As you can see from Listing 1 above, the Set interface extends the Collection interface. In keeping with the general form of object-oriented design, Set is more specialized than Collection. Therefore, Set makes the contract for the add() method more specific for objects of type Set. Here is some of the material from the Sun JDK 1.3 documentation describing the contract of the add() method for any class that implements the Set interface.
"Adds the specified element to this set if it is not already present... If this set already contains the specified element, the call leaves this set unchanged and returns false... this ensures that sets never contain duplicate elements."
How do the contracts differ?
The contract for the add() method, as declared in the Collection interface, does not prohibit duplicate elements, but does make the provision for interfaces that extend Collection to prohibit duplicate elements.
The contract for the add() method in the Set interface does prohibit duplicate elements.
What about the List interface?
I'm not going to show it here, but the contract for the add() method declared in the List interface, (which extends Collection), does not prohibit duplicate elements. However, it does have some other requirements that don't apply to Set objects.
A major difference
This is one of the major differences between lists and sets in the Java Collection Framework. Both List objects and Set objects are collections, because both of the interfaces extend the Collection interface. However, the Set interface contract prohibits duplicate elements while the List interface contract does not prohibit duplicate elements.
Designing a framework
In theory, it should be possible (but perhaps not very practical) to define a framework consisting solely of interface definitions and associated contracts for methods and algorithms. Then each user could implement the interfaces however they see fit, provided that they comply with the contracts. (This might not be very practical because every user of the framework would then be required to implement the interfaces, which would entail a lot of work.)
The SAX framework
As an aside, I'm aware of one case in which this was done successfully. Although I wasn't involved, I have read that the Simple API for XML (SAX) was initially defined as a set of interface definitions and contracts (and possibly a few concrete implementations). Further, I have been led to believe that the framework was designed by a group of volunteers working cooperatively via the Internet.
Several companies have since provided free or low-cost implementations of the interfaces, resulting in a very convenient way to use Java to parse XML documents. (There are several tutorial lessons on the use of SAX on my web site.) One of these companies is IBM, which has made the XML4J parser available. I have found the XML4J parser to be very usable.
Now, back to the main thread
Fortunately, Sun didn't stop work after defining the interfaces and contracts for the Java Collections Framework. Rather, they also provided us with several useful classes that implement the interfaces in the framework. Thus, we can instantiate and use objects of those classes immediately without having to define them ourselves. Here is a list of the concrete implementation classes in the Java Collections Framework as defined in JDK 1.3.
As is always the case, each of the core interfaces defines a data type. Each interface declares several methods. In addition, each interface provides a contract that applies to each declared method. The contracts become more specific as we traverse down the interface inheritance hierarchy.
Objects instantiated from classes that implement the interfaces can be considered to be of the interface type.
The method declarations and their associated contracts in the interfaces specify the general behavior of matching methods in the classes that implement the interfaces.
The framework provides nine concrete implementations of the interfaces that we can use to instantiate new objects to use as data structures.
The framework also provides three abstract implementations that we can
use as a starting point for defining our own implementations.
In the next lesson, I will begin a discussion of the nine concrete implementations provided in the Collections Framework. I will also discuss the algorithms in that lesson.
Copyright 2000, Richard G. Baldwin. Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.
Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two. He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.