Chapter 10.1.4 The Java Collection Framework | Introduction to Programming Using Java

Chapter 10.1.4  The Java Collection Framework | Introduction to Programming Using Java

 

10.1.4  The Java Collection Framework

 

Java’s generic data structures can be divided into two categories: collections and maps. A collection is more or less what it sound like: a collection of objects. A map associates objects in one set with objects in another set in the way that a dictionary associates definitions with words or a phone book associates phone numbers with names.

A map is similar to what I called an “association list” in Subsection 7.4.2. In Java, collections and maps are represented by the parameterized interfaces Collection<T> and Map<T,S>. Here, “T” and “S” stand for any type except for the primitive types. Map<T,S> is the first example we have seen where there are two type parameters, T and S; we will not deal further with this possibility until we look at maps more closely in Section 10.3. In this section and the next, we look at collections only.

 

Chapter 10.1.4  The Java Collection Framework | Introduction to Programming Using Java

 

There are two types of collections: lists and sets. A list is a collection in which the objects are arranged in a linear sequence. A list has a first item, a second item, and so on. For any item in the list, except the last, there is an item that directly follows it. The defining property of a set is that no object can occur more than once in a set; the elements of a set are not necessarily thought of as being in any particular order.

The ideas of lists and sets are represented as parameterized interfaces List<T> and Set<T>. These are sub-interfaces of Collection<T>. That is, any object that implements the interface List<T> or Set<T> automatically implements Collection<T> as well. The interface Collection<T> specifies general operations that can be applied to any collection at all. List<T> and Set<T> add additional operations that are appropriate for lists and sets respectively.

Of course, any actual object that is a collection, list, or set must belong to a concrete class that implements the corresponding interface. For example, the class ArrayList<T> implements the interface List<T> and therefore also implements Collection<T>.

 

Chapter 10.1.4 The Java Collection Framework | Introduction to Programming Using Java

 

This means that all the methods that are defined in the list and collection interfaces can be used with, for example, an ArrayList<String> object. We will look at various classes that implement the list and set interfaces in the next section. But before we do that, we’ll look briefly at some of the general operations that are available for all collections.

∗ ∗ ∗

The interface Collection<T> specifies methods for performing some basic operations on any collection of objects. Since “collection” is a very general concept, operations that can be applied to all collections are also very general. They are generic operations in the sense that they can be applied to various types of collections containing various types of objects.

Suppose that coll is an object that implements the interface Collection<T> (for some specific non-primitive type T). Then the following operations, which are specified in the interface Collection<T>, are defined for coll:

  • size() — returns an int that gives the number of objects in the collection.
  • isEmpty() — returns a boolean value which is true if the size of the collection is 0.
  • clear() — removes all objects from the collection.
  • add(tobject) — adds tobject to the collection. The parameter must be of type T; if not, a syntax error occurs at compile time. This method returns a boolean value which tells you whether the operation actually modified the collection. For example, adding an object to a Set has no effect if that object was already in the set.
  • contains(object) — returns a boolean value that is true if object is in the collection. Note that object is not required to be of type T, since it makes sense to check whether object is in the collection, no matter what type object has. (For testing equality, null is considered to be equal to itself. The criterion for testing non-null objects for equality can differ from one kind of collection to another; see Subsection 10.1.6, below.)
  • remove(object)— removes object from the collection, if it occurs in the collection, and returns a boolean value that tells you whether the object was found. Again, object is not required to be of type T.
  • containsAll(coll2) — returns a boolean value that is true if every object in coll2 is also in the coll. The parameter can be any collection.
  • addAll(coll2) — adds all the objects in coll2 to coll. The parameter, coll2, can be any collection of type Collection<T>. However, it can also be more general. For example, if T is a class and S is a sub-class of T, then coll2 can be of type Collection<S>. This makes sense because any object of type S is automatically of type T and so can legally be added to coll.
  • removeAll(coll2) — removes every object from coll that also occurs in the collection coll2. coll2 can be any collection.
  • retainAll(coll2) — removes every object from coll that does not occur in the collection coll2. It “retains” only the objects that do occur in coll2. coll2 can be any collection.
  • toArray() — returns an array of type Object[ ] that contains all the items in the collection. The return value can be type-cast to another array type, if appropriate. Note that the return type is Object[ ], not T[ ]! However, you can type-cast the return value to a more specific type. For example, if you know that all the items in coll are of type String, then (String[])coll.toArray() gives you an array of Strings containing all the strings in the collection.

Since these methods are part of the Collection<T> interface, they must be defined for every object that implements that interface. There is a problem with this, however. For example, the size of some kinds of collection cannot be changed after they are created. Methods that add or remove objects don’t make sense for these collections. While it is still legal to call the methods, an exception will be thrown when the call is evaluated at run time.

 

Chapter 10.1.4  The Java Collection Framework | Introduction to Programming Using Java

 

The type of the exception is UnsupportedOperationException. Furthermore, since Collection<T> is only an interface, not a concrete class, the actual implementation of the method is left to the classes that implement the interface. This means that the semantics of the methods, as described above, are not guaranteed to be valid for all collection objects; they are valid, however, for classes in the Java Collection Framework.

There is also the question of efficiency. Even when an operation is defined for several types of collections, it might not be equally efficient in all cases. Even a method as simple as size() can vary greatly in efficiency.

For some collections, computing the size() might involve counting the items in the collection. The number of steps in this process is equal to the number of items. Other collections might have instance variables to keep track of the size, so evaluating size() just means returning the value of a variable.

In this case, the computation takes only one step, no matter how many items there are. When working with collections, it’s good to have some idea of how efficient operations are and to choose a collection for which the operations that you need can be implemented most efficiently. We’ll see specific examples of this in the next two sections.

 

 

Chapter 10.1.4  The Java Collection Framework | Introduction to Programming Using Java

 

 

 

SEE MORE: