Академический Документы
Профессиональный Документы
Культура Документы
Program design often requires handling of groups of objects. The collections framework
presents a set of standard utility classes for managing such collections. This framework is
provided in the java.util package and comprises three main parts:
Core Interfaces
The elements in a Set must be unique, that is, no two elements in the set can be equal.
The order of elements in a List is retained, and individual elements can be accessed
according to their position in the list.
As can be seen from, the Map interface does not extend the Collection interface because
conceptually, a map is not a collection. A map does not contain elements. It contains
mappings (also called entries) from a set of key objects to a set of value objects. A key
can, at most, be associated with one value. As the name implies, the SortedMap interface
extends the Map interface to maintain its mappings sorted in key order.
11.2 Collections
The Collection interface specifies the contract that all collections should implement.
Some of the operations in the interface are optional, meaning that a collection may
choose to provide a stub implementation of such an operation that throws an
UnsupportedOperationException when invoked. The implementations of collections
from the java.util package support all the optional operations in the Collection
interface .Many of the methods return a boolean value to indicate whether the collection
was modified as a result of the operation.
Basic Operations
The basic operations are used to query a collection about its contents and allow elements
to be added and removed from a collection.
int size()
boolean isEmpty()
boolean contains(Object element)
boolean add(Object element) // Optional
boolean remove(Object element) // Optional
The add() and remove() methods return true if the collection was modified as a result
of the operation.
By returning the value false, the add() method indicates that the collection excludes
duplicates, and that the collection already contains an object equal to the argument object.
The contains() method checks for membership of the argument object in the collection
using object value equality.
Bulk Operations
boolean containsAll(Collection c)
boolean addAll(Collection c) // Optional
boolean removeAll(Collection c) // Optional
boolean retainAll(Collection c) // Optional
void clear() // Optional
These bulk operations can be used to perform the equivalent of set logic on arbitrary
collections (not just on sets). The containsAll() method returns true if all elements of
the specified collection are also contained in the current collection.
The addAll(), removeAll(), and retainAll() methods are destructive in the sense that the
collection on which they are invoked can be modified.
Array Operations
Object[] toArray()
Object[] toArray(Object a[])
The first toArray() method returns an array with all the elements of the collection. The
second method stores the elements of a collection into an array of a specified type.
If the given array is big enough, the elements are stored in this array. If there is room to
spare in the array, that is, the length of the array is greater than the number of elements in
the collection, the spare room is filled with null values before the array is returned. If the
array is too small, a new array of the same runtime type and appropriate size is created.
Iterators
Iterator iterator()
boolean hasNext()
Returns true if the underlying collection still has elements left to return. A future call to
the next() method will return the next element from the collection.
Object next()
Moves the iterator to the next element in the underlying collection, and returns the
current element. If there are no more elements left to return, it throws a
NoSuchElementException.
Object remove()
Removes the element that was returned by the last call to the next() method, from the
underlying collection. Invoking this method results in an IllegalStateException, if the
next() method has not yet been called, or when the remove() method has already been
called after the last call to the next() method. This method is optional for an iterator, that
is, it throws an UnsupportedOperationException if the remove operation is not
supported.
After obtaining the iterator for a collection, the methods provided by the Iterator
interface can be used to systematically traverse the elements of the underlying collection
one by one.
11.3 Sets
Multisets (a.k.a. bags) that allow duplicate elements cannot be implemented using the
Set interface since this interface requires that elements are unique in the collection.
Table 11.3. Bulk Operations and Set Logic
The HashSet class implements the Set interface. Since this implementation uses a hash
table, it offers near constant-time performance for most operations. A HashSet does not
guarantee any ordering of the elements. However, the LinkedHashSet subclass of
HashSet guarantees insertion-order. The sorted counterpart is TreeSet. A HashSet relies
on the implementation of the hashCode() and equals() methods of its. The hashCode()
method is used for hashing the elements, and the equals() method is needed for
comparing elements. In fact, the equality and the hash codes of HashSets are defined in
terms of the equality and the hash codes of their elements.
The LinkedHashSet class offers constructors analogous to the ones in the HashSet class.
The initial capacity (i.e., the number of buckets in the hash table) and its load factor (i.e.,
the ratio of number of elements stored to its current capacity) can be tuned when the set is
created. The default values for these parameters will under most circumstances provide
acceptable performance.
HashSet()
HashSet(Collection c)
Constructs a new set containing the elements in the specified collection. The new set will
not contain any duplicates. This offers a convenient way to remove duplicates from a
collection.
HashSet(int initialCapacity)
Constructs a new, empty set with the specified initial capacity and the specified load
factor.
11.4 Lists
Lists are collections that maintain their elements in order, and can contain duplicates. The
elements in a list are ordered. Each element, therefore, has a position in the list. A zero-
based index can be used to access the element at the position designated by the index
value. The position of an element can change as elements are inserted or deleted from the
list.
In addition to the operations inherited from the Collection interface, the List interface
also defines operations that work specifically on lists: position-based access of the list
elements, searching in a list, creation of customized iterators, and operations on parts of a
list (called open range-view operations). This additional functionality is provided by the
following methods in the List interface:
Replaces the element at the specified index with the specified element. It returns the
previous element at the specified index.
Inserts the specified element at the specified index. If necessary, it shifts the element
previously at this index and any subsequent elements one position toward the end of the
list. The inherited method add(Object) from the Collection interface will append the
specified element to the end of the list.
Object remove(int index) Optional
Deletes and returns the element at the specified index, contracting the list accordingly.
The inherited method remove(Object) from the Collection interface will remove the
first occurrence of the element from the list.
Inserts the elements from the specified collection at the specified index, using the iterator
of the specified collection. The method returns true if any elements were added.
In a non-empty list, the first element is at index 0 and the last element is at size()-1. As
might be expected, all methods throw an IndexOutOfBoundsException if an illegal
index is specified.
// Element Search
int indexOf(Object o)
int lastIndexOf(Object o)
These methods respectively return the index of the first and the last occurrence of the
element in the list if the element is found; otherwise, the value –1 is returned.
// List Iterators
ListIterator listIterator()
ListIterator listIterator(int index)
The iterator from the first method traverses the elements consecutively, starting with the
first element of the list, whereas the iterator from the second method starts traversing the
list from the element indicated by the specified index.
boolean hasNext();
boolean hasPrevious();
The ListIterator interface is a bidirectional iterator for lists. It extends the Iterator
interface and allows the list to be traversed in either direction. When traversing lists, it
can be helpful to imagine a cursor moving forward or backward between the elements
when calls are made to the next() and the previous() method, respectively. The
element that the cursor passes over is returned. When the remove() method is called, the
element last passed over is removed from the list.
// Open Range-View
List subList(int fromIndex, int toIndex)
This method returns a view of the list, which consists of the sublist of the elements from
the index fromIndex to the index toIndex-1. A view allows the range it represents in the
underlying list to be manipulated. Any changes in the view are reflected in the underlying
list, and vice versa. Views can be used to perform operations on specific ranges of a list.
Three implementations of the List interface are provided in the java.util package:
ArrayList, LinkedList, and Vector.
The ArrayList class implements the List interface. The Vector class is a legacy class
that has been retrofitted to implement the List interface. The Vector and ArrayList
classes are implemented using dynamically resizable arrays, providing fast random
access and fast list traversal—very much like using an ordinary array. Unlike the
ArrayList class, the Vector class is thread-safe, meaning that concurrent calls to the
vector will not compromise its integrity.
The ArrayList and Vector classes offer comparable performance, but Vector objects
suffer a slight performance penalty due to synchronization. Position-based access has
constant-time performance for the ArrayList and Vector classes. However, position-
based access is in linear time for a LinkedList, owing to traversal in a doubly-linked
list. When frequent insertions and deletions occur inside a list, a LinkedList can be
worth considering. In most cases, the ArrayList implementation is the over-all best
choice for implementing lists.
The ArrayList class provides the following constructors:
ArrayList()
ArrayList(Collection c)
Constructs a new ArrayList containing the elements in the specified collection. The new
ArrayList will retain any duplicates. The ordering in the ArrayList will be determined
by the traversal order of the iterator for the collection passed as argument. An analogous
constructor is provided by the LinkedList and Vector classes.
ArrayList(int initialCapacity)
Constructs a new, empty ArrayList with the specified initial capacity. An analogous
constructor is provided by the Vector class.
11.5 Maps
A Map defines mappings from keys to values. The <key, value> pair is called an entry. A
map does not allow duplicate keys, in other words, the keys are unique. Each key maps to
one value at the most, implementing what is called a single-valued map. Thus, there is a
many-to-one relation between keys and values. For example, in a student-grade map, a
grade (value) can be awarded to many students (keys), but each student has only one
grade.
Both the keys and the values must be objects. This means that primitive values must be
wrapped in their respective wrapper objects, if they are to be put in a map.
A map is not a collection and the Map interface does not extend the Collection interface.
However, the mappings can be viewed as a collection in various ways: a key set, a value
collection, or an entry set. These collection views are the only means of traversing a map.
The Map interface specifies some optional methods. Implementations should throw an
UnsupportedOperationException if they do not support such an operation.
Basic Operations
Inserts the <key, value> entry into the map. It returns the value previously associated
with the specified key, if any. Otherwise, it returns the null value.
Object get(Object key)
Returns the value to which the specified key is mapped, or null if no entry is found.
The remove() method deletes the entry for the specified key. It returns the value
previously associated with the specified key, if any. Otherwise, it returns the null value.
Returns true if there exists one or more keys that are mapped to the specified value.
int size()
boolean isEmpty()
These methods return the number of entries (i.e., number of unique keys in the map) and
whether the map is empty or not.
Bulk Operations
The first method copies all entries from the specified map to the current map, and the
second method deletes all the entries from the current map.
Collection Views
Set keySet()
Collection values()
Set entrySet()
These methods provide different views of a map. Changes in the map are reflected in the
view, and vice versa. These methods return a set view of keys, a collection view of values
and a set view of <key, value> entries, respectively. Note that the Collection returned
by the values() method is not a Set, as several keys can map to the same value, that is,
duplicate values can be included in the returned collection. Each <key, value> in the
entry set view is represented by an object implementing the nested Map.Entry interface.
An entry in the entry set view can be manipulated by methods defined in this interface,
which are self-explanatory:
interface Entry {
Object getKey();
Object getValue();
Object setValue(Object value);
}
The classes HashMap and Hashtable implement unordered maps. The class
LinkedHashMap implements ordered maps, which are discussed below. The class
TreeMap implements sorted maps .
While the HashMap class is not thread-safe and permits one null key, the Hashtable
class is thread-safe and permits non-null keys and values only. The thread-safety the
Hashtable class provides has a performance penalty. Thread-safe use of maps is also
provided by the methods in the Collections class. These map implementations are
based on a hashing algorithm. Operations on a map thus rely on the hashCode() and
equals() methods of the key objects
Both the HashMap and LinkedHashMap classes provide comparable performance, but the
HashMap class is the natural choice if ordering is not an issue. Operations such as adding,
removing, or finding an entry based on a key are constant time, as these hash the key..
Adding, removing, and finding entries in a LinkedHashMap can be slightly slower than in
a HashMap, as an ordered doubly-linked list has to be maintained. Traversal of a map is
through one of its collection-views. For an underlying LinkedHashMap, the traversal time
is proportional to the size of the map—regardless of its capacity. However, for an
underlying HashMap, it is proportional to the capacity of the map.
The concrete map classes override the toString() method. The standard textual
representation generated by the toString() method for a map is
where each keyi and each valuei is the textual representation generated by the
toString() method of the individual key and value objects in the map, respectively.
As was the case with collections, implementation classes provide a standard constructor
that creates a new empty map, and a constructor that creates a new map based on an
existing one. These classes also create a new empty map with an initial capacity and/or
load factor. The HashMap class provides the following constructors:
HashMap()
HashMap(int initialCapacity)
HashMap(int initialCapacity, float loadFactor)
Constructs a new, empty HashMap, using either specified or default initial capacity and
load factor.
HashMap(Map otherMap)
The LinkedHashMap and Hashtable classes have constructors analogous to the four
constructors for the HashMap class. In addition, the LinkedHashMap class provides a
constructor where the ordering mode can also be specified:
Constructs a new, empty LinkedHashMap with the specified initial capacity, the specified
load factor, and the specified ordering mode. The ordering mode is true for access order
and false for key insertion order.
Sets and maps have special interfaces, called SortedSet and SortedMap, for
implementations that sort their elements in a specific order .
Objects can specify their natural order by implementing the Comparable interface, or be
dictated a total order by a comparator object that implements the Comparator interface.
We'll first look at the two interfaces Comparable and Comparator, before discussing
sorted sets and maps.
The compare() method returns a negative integer, zero, or a positive integer if the first
object is less than, equal to, or greater than the second object, according to the total order.
Since this method tests for equality, it is strongly recommended that its implementation
does not contradict the semantics of the equals() method (see Section 11.7).
The Comparable Interface
A class can define the natural order of its instances by implementing the Comparable
interface. Many of the standard classes in the Java API, such as the wrapper classes,
String, Date, and File, implement this interface. The java.lang.Comparable interface
specifies a single method:
int compareTo(Object o)
This method returns a negative integer, zero, or a positive integer if the current object is
less than, equal to, or greater than the specified object, based on the natural order. It
throws a ClassCastException if the reference value passed in the argument cannot be
cast to the type of the current object. Since this method tests for equality, it is
recommended that its implementation does not contradict the semantics of the equals()
method.
Note that the natural order for String objects (and Character objects) is lexicographical
order. Strings will be lexicographically maintained as elements in a sorted set or as keys
in a sorted map that uses natural ordering. A collection of strings sorted by natural order
would be ordered in lexicographical order.
The natural order for objects of a numerical wrapper type is ascending order of the values
of the corresponding numerical primitive type. As elements in a sorted set, or as keys in a
sorted map, the objects would be maintained in ascending order.