epubjs
Version:
Render ePub documents in the browser, across many devices
365 lines • 108 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Collections</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Collections"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-11-SECT-4"/>Collections</h1></div></div></div><p><a id="I_indexterm11_id741199" class="indexterm"/> <span class="emphasis"><em>Collections</em></span> are data structures that
are fundamental to all types of programming. Whenever we need to refer to
a group of objects, we have some kind of collection. At the core language
level, Java supports collections in the form of arrays. But arrays are
static and because they have a fixed length, they are awkward for groups
of things that grow and shrink over the lifetime of an application. Arrays
also do not represent abstract relationships between objects well. In the
early days, the Java platform had only two basic classes to address these
needs: the <code class="literal">java.util.Vector</code> class,
which represents a dynamic list of objects, and the <code class="literal">java.util.Hashtable</code> class, which holds a map of
key/value pairs. Today, Java has a more comprehensive approach to
collections called the Collections Framework. The older classes still
exist, but they have been retrofitted into the framework (with some
eccentricities) and are generally no longer used.</p><p>Though conceptually simple, collections are one of the most powerful
parts of any programming language. Collections implement data structures
that lie at the heart of managing complex problems. A great deal of basic
computer science is devoted to describing the most efficient ways to
implement certain types of algorithms over collections. Having these tools
at your disposal and understanding how to use them can make your code both
much smaller and faster. It can also save you from reinventing the
wheel.</p><p>Prior to Java 5, the Collections Framework had two major drawbacks.
The first was that—not having generic types to work with—collections were
by necessity untyped and worked only with anonymous <code class="literal">Object</code>s instead of real types like <code class="literal">Date</code>s and <code class="literal">String</code>s. This meant that you had to perform a
type cast every time you took an object out of a collection. This flew in
the face of Java’s compile-time type safety. But in practice, this was
less a problem than it was just plain cumbersome and tedious. The second
issue was that, for practical reasons, collections could work only with
objects and not with primitive types. This meant that any time you wanted
to put a number or other primitive type into a collection, you had to
store it in a wrapper class first and unpack it later upon retrieving it.
The combination of these factors made code working with collections less
readable and more dangerous to boot.</p><p>This all changed with the introduction of generic types and
autoboxing of primitive values. First, the introduction of generic types,
as we described in <a class="xref" href="ch08.html" title="Chapter 8. Generics">Chapter 8</a>, has made it
possible for truly typesafe collections to be under the control of the
programmer. Second, the introduction of autoboxing and unboxing of
primitive types means that you can generally treat objects and primitives
as equals where collections are concerned. The combination of these new
features can significantly reduce the amount of code you write and add
safety as well. As we’ll see, all of the collections classes now take
advantage of these features.</p><p>The Collections Framework is based around a handful of interfaces in
the <code class="literal">java.util</code> package. These interfaces
are divided into two hierarchies. The first hierarchy descends from the
<code class="literal">Collection</code> interface. This interface
(and its descendants) represents a container that holds other objects. The
second, separate hierarchy is based on the <code class="literal">Map</code> interface, which represents a group of
key/value pairs where the key can be used to retrieve the value in an
efficient way.</p><div class="sect2" title="The Collection Interface"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-11-SECT-4.1"/>The Collection Interface</h2></div></div></div><p><a id="idx10612" class="indexterm"/>The mother of all collections is an interface
appropriately named <code class="literal">Collection</code>. It
serves as a container that holds other objects, its
<span class="emphasis"><em>elements</em></span>. It doesn’t specify exactly how the
objects are organized; it doesn’t say, for example, whether duplicate
objects are allowed or whether the objects are ordered in any way. These
kinds of details are left to child interfaces. Nevertheless, the
<code class="literal">Collection</code> interface defines some
basic operations common to all collections:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public boolean add(</code>
<em class="replaceable"><code>element</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id741365" class="indexterm"/>This method adds the supplied object to this
collection. If the operation succeeds, this method returns
<code class="literal">true</code>. If the object already
exists in this collection and the collection does not permit
duplicates, <code class="literal">false</code> is returned.
Furthermore, some collections are read-only. Those collections
throw an <code class="literal">UnsupportedOperationException</code> if this
method is called.</p></dd><dt><span class="term"><code class="literal">public boolean remove(</code>
<em class="replaceable"><code>element</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id741411" class="indexterm"/>This method removes the specified object from this
collection. Like the <code class="literal">add()</code>
method, this method returns <code class="literal">true</code> if the object is removed from the
collection. If the object doesn’t exist in this collection,
<code class="literal">false</code> is returned. Read-only
collections throw an <code class="literal">UnsupportedOperationException</code> if this
method is called.</p></dd><dt><span class="term"><code class="literal">public boolean contains(</code>
<em class="replaceable"><code>element</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id741462" class="indexterm"/>This method returns <code class="literal">true</code> if the collection contains the
specified object.</p></dd><dt><span class="term"><code class="literal">public int size()</code></span></dt><dd><p>Use this method to find the number of elements in this
collection.</p></dd><dt><span class="term"><code class="literal">public boolean
isEmpty()</code></span></dt><dd><p><a id="I_indexterm11_id741494" class="indexterm"/>This method returns <code class="literal">true</code> if this collection has no
elements.</p></dd><dt><span class="term"><code class="literal">public Iterator
iterator()</code></span></dt><dd><p><a id="I_indexterm11_id741518" class="indexterm"/>Use this method to examine all the elements in this
collection. This method returns an <code class="literal">Iterator</code>, which is an object you can use
to step through the collection’s elements. We’ll talk more about
iterators in the next section.</p></dd></dl></div><p>Additionally, the methods <a id="I_indexterm11_id741536" class="indexterm"/><code class="literal">addAll()</code>, <a id="I_indexterm11_id741546" class="indexterm"/><code class="literal">removeAll()</code>, and
<a id="I_indexterm11_id741557" class="indexterm"/><code class="literal">containsAll()</code> accept
another <code class="literal">Collection</code> and add, remove,
or test for all of the elements of the supplied collection.</p><div class="sect3" title="Generics and collections"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.1.1"/>Generics and collections</h3></div></div></div><p><a id="I_indexterm11_id741581" class="indexterm"/> <a id="I_indexterm11_id741592" class="indexterm"/>When using generics, the <code class="literal">Collection</code> type is parameterized with a
specific type of element that the collection will hold. This makes a
generic collection of “anything” into a specific collection of some
type of element. The parameter type becomes the compile-time type of
the <code class="literal">element</code> arguments in all of the
methods of <code class="literal">Collection</code> (in this
case, the <code class="literal">add()</code>, <code class="literal">remove()</code>, and <code class="literal">contains()</code> methods listed earlier). For
example, in the following code, we create a <code class="literal">Collection</code> that works with <code class="literal">Date</code>s:</p><a id="I_11_tt705"/><pre class="programlisting"> <code class="n">Collection</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">dates</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o"><</code><code class="n">Date</code><code class="o">>();</code> <code class="c1">// = new ArrayList<>() would </code>
<code class="c1">// also work.</code>
<code class="n">dates</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">);</code>
<code class="n">dates</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="s">"foo"</code> <code class="o">)</code> <code class="c1">// Error; string type where Date expected!!</code></pre><p><code class="literal">ArrayList</code> is just one
implementation of <code class="literal">Collection</code>; we’ll
talk about it a bit later. The important thing is that we’ve declared
the variable <code class="literal">dates</code> to be of the
type <code class="literal">Collection<Date></code>; that
is, a collection of <code class="literal">Date</code>s, and
we’ve allocated our <code class="literal">ArrayList</code> to
match. Because our collection has been parameterized with the type
<code class="literal">Date</code>, the <code class="literal">add()</code> method of the collection becomes
<code class="literal">add( Date date )</code> and attempting to
add any type of object other than a <code class="literal">Date</code> to the list would have caused a
compile-time error.</p><p>If you are working with very old Java code that predates
generics, you can simply drop the types and perform the appropriate
casts. For example:</p><a id="I_11_tt706"/><pre class="programlisting"> <code class="n">Collection</code> <code class="n">dates</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o">();</code>
<code class="n">dates</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">);</code> <code class="c1">// unchecked, compile-time warning</code>
<code class="n">Date</code> <code class="n">date</code> <code class="o">=</code> <code class="o">(</code><code class="n">Date</code><code class="o">)</code><code class="n">dates</code><code class="o">.</code><code class="na">get</code><code class="o">(</code> <code class="mi">0</code> <code class="o">);</code></pre><p>In this case, we’ll get a compile time warning that we’re using
<code class="literal">ArrayList </code>in a potentially unsafe
(nongeneric typesafe) way.</p><p>As we’ve described earlier in the book, this is essentially what
the Java compiler is doing for us with generics. When using
collections (or any generic classes) in this way under Java 5 or
later, you will get compile-time warnings indicating that the usage is
unchecked, meaning that it is possible to get an error at runtime if
you have made a mistake. In this example, a mistake would not be
caught until someone tried to retrieve the object from the collection
and cast it to the expected type.</p></div><div class="sect3" title="Legacy code and runtime type safety"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.1.2"/>Legacy code and runtime type safety</h3></div></div></div><p><a id="idx10597" class="indexterm"/> <a id="idx10647" class="indexterm"/> <a id="idx10669" class="indexterm"/>If you are working with legacy Java code that predates
Java 5 generics and you do not wish to introduce generics to it, you
can still add a layer of type safety at runtime by switching to a
runtime type-checked version of your collection types. Java supplies
runtime-checked wrappers for all of the basic collection types. These
wrappers enforce a specific Java element type at runtime by throwing
<a id="I_indexterm11_id741799" class="indexterm"/><code class="literal">ClassCastException</code> if
the wrong element is inserted. For example:</p><a id="I_11_tt707"/><pre class="programlisting"> <code class="n">List</code> <code class="n">list</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o">();</code>
<code class="n">list</code> <code class="o">=</code> <code class="n">Collections</code><code class="o">.</code><code class="na">checkedList</code><code class="o">(</code> <code class="n">list</code><code class="o">,</code> <code class="n">Date</code><code class="o">.</code><code class="na">class</code> <code class="o">);</code>
<code class="n">list</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">);</code>
<code class="n">list</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="s">"foo"</code> <code class="o">);</code> <code class="c1">// Runtime ClassCastException!</code></pre><p>Here, the static <a id="I_indexterm11_id741823" class="indexterm"/><code class="literal">Collections.checkedList()</code> method has wrapped
our collection, <code class="literal">list</code>, in a wrapper
that implements all of the methods of <code class="literal">List</code>, but checks that we are only holding
<code class="literal">Date</code>s. The second argument to the
method is the literal <code class="literal">Date.class</code>
reference to the <code class="literal">Class</code> of <code class="literal">Date</code>. This serves to tell the wrapper what
type we want to enforce. Corresponding “checked” collection methods
exist for all of the basic collection interfaces that we’ll see,
including the base <code class="literal">Collection</code>,
<code class="literal">List</code>, <code class="literal">Set</code>, and <code class="literal">Map</code>.<a id="I_indexterm11_id741893" class="indexterm"/><a id="I_indexterm11_id741900" class="indexterm"/><a id="I_indexterm11_id741907" class="indexterm"/></p></div><div class="sect3" title="Converting between collections and arrays"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.1.3"/>Converting between collections and arrays</h3></div></div></div><p><a id="I_indexterm11_id741921" class="indexterm"/> <a id="I_indexterm11_id741930" class="indexterm"/>Converting between collections and arrays is easy. For
convenience, the elements of a collection can be retrieved as an array
using the following methods:</p><a id="I_11_tt708"/><pre class="programlisting"> <code class="kd">public</code> <code class="n">Object</code><code class="o">[]</code> <code class="nf">toArray</code><code class="o">()</code>
<code class="kd">public</code> <code class="o"><</code><code class="n">E</code><code class="o">></code> <code class="n">E</code><code class="o">[]</code> <code class="n">toArray</code><code class="o">(</code> <code class="n">E</code><code class="o">[]</code> <code class="n">a</code> <code class="o">)</code></pre><p>The first method returns a plain <code class="literal">Object</code> array. With the second form, we can
be more specific and get back an array of the correct element type. If
we supply an array of sufficient size, it will be filled in with the
values. But if the array is too short (e.g., zero length), a new array
of the <span class="emphasis"><em>same type but the required length</em></span> will be
created and returned to us. So you can just pass in an empty array of
the correct type like this:</p><a id="I_11_tt709"/><pre class="programlisting"> <code class="n">Collection</code><code class="o"><</code><code class="n">String</code><code class="o">></code> <code class="n">myCollection</code> <code class="o">=</code> <code class="o">...;</code>
<code class="n">String</code> <code class="o">[]</code> <code class="n">myStrings</code> <code class="o">=</code> <code class="n">myCollection</code><code class="o">.</code><code class="na">toArray</code><code class="o">(</code> <code class="k">new</code> <code class="n">String</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code> <code class="o">);</code></pre><p>(This trick is a little awkward and it would be nice if Java let
us specify the type explicitly using a <code class="literal">Class</code> reference, but for some reason, this
isn’t the case.) Going the other way, you can convert an array of
objects to a <code class="literal">List</code> collection with
the static <code class="literal">asList()</code> method of the
<code class="literal">java.util.Arrays</code> class:<a id="I_indexterm11_id742004" class="indexterm"/></p><a id="I_11_tt710"/><pre class="programlisting"> <code class="n">String</code> <code class="o">[]</code> <code class="n">myStrings</code> <code class="o">=</code> <code class="o">...;</code> <code class="n">List</code> <code class="n">list</code> <code class="o">=</code> <code class="n">Arrays</code><code class="o">.</code><code class="na">asList</code><code class="o">(</code> <code class="n">myStrings</code> <code class="o">);</code></pre></div></div><div class="sect2" title="Iterator"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-11-SECT-4.2"/>Iterator</h2></div></div></div><p><a id="idx10617" class="indexterm"/>An <a id="I_indexterm11_id742042" class="indexterm"/><span class="emphasis"><em>iterator</em></span> is an object that lets you
step through a sequence of values. This kind of operation comes up so
often that it is given a standard interface: <code class="literal">java.util.Iterator</code>. The <a id="I_indexterm11_id742059" class="indexterm"/><code class="literal">Iterator</code> interface has
only two primary methods:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public E next()</code></span></dt><dd><p><a id="I_indexterm11_id742080" class="indexterm"/>This method returns the next element (an element of
generic type E) of the associated collection.</p></dd><dt><span class="term"><code class="literal">public boolean
hasNext()</code></span></dt><dd><p><a id="I_indexterm11_id742097" class="indexterm"/>This method returns <code class="literal">true</code> if you have not yet stepped through
all the <code class="literal">Collection</code>’s elements.
In other words, it returns <code class="literal">true</code>
if you can call <code class="literal">next()</code> to get
the next element.</p></dd></dl></div><p>The following example shows how you could use an <code class="literal">Iterator</code> to print out every element of a
collection:</p><a id="I_11_tt711"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">printElements</code><code class="o">(</code><code class="n">Collection</code> <code class="n">c</code><code class="o">,</code> <code class="n">PrintStream</code> <code class="n">out</code><code class="o">)</code> <code class="o">{</code>
<code class="n">Iterator</code> <code class="n">iterator</code> <code class="o">=</code> <code class="n">c</code><code class="o">.</code><code class="na">iterator</code><code class="o">();</code>
<code class="k">while</code> <code class="o">(</code> <code class="n">iterator</code><code class="o">.</code><code class="na">hasNext</code><code class="o">()</code> <code class="o">)</code>
<code class="n">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">iterator</code><code class="o">.</code><code class="na">next</code><code class="o">()</code> <code class="o">);</code>
<code class="o">}</code></pre><p>In addition to the traversal methods, <code class="literal">Iterator</code> provides the ability to remove an
element from a collection:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public void remove()</code></span></dt><dd><p><a id="I_indexterm11_id742163" class="indexterm"/>This method removes the most recent object returned
from <code class="literal">next()</code> from the associated
<code class="literal">Collection</code>.</p></dd></dl></div><p>Not all iterators implement <code class="literal">remove()</code>. It doesn’t make sense to be able to
remove an element from a read-only collection, for example. If element
removal is not allowed, an <code class="literal">UnsupportedOperationException</code> is thrown from
this method. If you call <code class="literal">remove()</code>
before first calling <code class="literal">next()</code>, or if
you call <code class="literal">remove()</code> twice in a row,
you’ll get an <code class="literal">IllegalStateException</code>.</p><div class="sect3" title="For loop over collections"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.2.1"/>For loop over collections</h3></div></div></div><p><a id="I_indexterm11_id742229" class="indexterm"/> <a id="I_indexterm11_id742240" class="indexterm"/> <a id="I_indexterm11_id742249" class="indexterm"/>A form of the <code class="literal">for</code>
loop, described in <a class="xref" href="ch04.html" title="Chapter 4. The Java Language">Chapter 4</a>, can operate
over all types of <a id="I_indexterm11_id742268" class="indexterm"/><code class="literal">Collection</code> objects.
For example, we can now step over all of the elements of a typed
collection of <code class="literal">Date</code> objects like
so:</p><a id="I_11_tt712"/><pre class="programlisting"> <code class="n">Collection</code><code class="o"><</code><code class="n">Date</code><code class="o">></code> <code class="n">col</code> <code class="o">=</code> <code class="o">...</code>
<code class="k">for</code><code class="o">(</code> <code class="n">Date</code> <code class="n">date</code> <code class="o">:</code> <code class="n">col</code> <code class="o">)</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">date</code> <code class="o">);</code></pre><p>This feature of the Java built-in <code class="literal">for</code> loop is called the “enhanced” <code class="literal">for</code> loop (as opposed to the pregenerics,
numeric-only <code class="literal">for</code> loop). The
enhanced <code class="literal">for</code> loop applies only to
<code class="literal">Collection</code> type collections, not
<code class="literal">Map</code>s. <code class="literal">Map</code>s are another type of beast that really
contain two distinct sets of objects (keys and values), so it’s not
obvious what your intentions would be in such a loop.</p></div><div class="sect3" title="java.util.Enumeration"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.2.2"/>java.util.Enumeration</h3></div></div></div><p><a id="I_indexterm11_id742351" class="indexterm"/> <a id="I_indexterm11_id742362" class="indexterm"/> <a id="idx10645" class="indexterm"/>Prior to the introduction of the Collections API there
was another iterator interface: <code class="literal">java.util.Enumeration</code>. It used the slightly
more verbose names <a id="I_indexterm11_id742389" class="indexterm"/><code class="literal">nextElement()</code> and
<a id="I_indexterm11_id742399" class="indexterm"/><code class="literal">hasMoreElements()</code>,
but accomplished the same thing. Many older classes provide <a id="I_indexterm11_id742411" class="indexterm"/><code class="literal">Enumeration</code>s where
they would now use <code class="literal">Iterator</code>. If you
aren’t worried about performance, you can just convert your <code class="literal">Enumeration</code> into a <code class="literal">List</code> with a static convenience method of the
<code class="literal">java.util.Collections</code>
class:<a id="I_indexterm11_id742445" class="indexterm"/></p><a id="I_11_tt713"/><pre class="programlisting"> <code class="n">Enumeration</code> <code class="n">myEnumeartion</code> <code class="o">=</code> <code class="o">...;</code>
<code class="n">List</code> <code class="n">list</code> <code class="o">=</code> <code class="n">Collections</code><code class="o">.</code><code class="na">list</code><code class="o">(</code> <code class="n">myEnumeration</code> <code class="o">);</code></pre></div></div><div class="sect2" title="Collection Types"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-11-SECT-4.3"/>Collection Types</h2></div></div></div><p><a id="idx10613" class="indexterm"/>The <code class="literal">Collection</code>
interface has three child interfaces. <code class="literal">Set</code> represents a collection in which duplicate
elements are not allowed. <code class="literal">List</code> is a
collection whose elements have a specific order. The <code class="literal">Queue</code> interface is a buffer for objects with a
notion of a “head” element that’s next in line for processing.</p><div class="sect3" title="Set"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.3.1"/>Set</h3></div></div></div><p><a id="I_indexterm11_id742514" class="indexterm"/> <a id="I_indexterm11_id742525" class="indexterm"/> <code class="literal">Set</code> has no methods
besides the ones it inherits from <code class="literal">Collection</code>. It simply enforces its
no-duplicates rule. If you try to add an element that already exists
in a <code class="literal">Set</code>, the <code class="literal">add()</code> method simply returns <code class="literal">false</code>. <code class="literal">SortedSet</code> maintains elements in a prescribed
order; like a sorted list that can contain no duplicates. It adds the
methods <code class="literal">add()</code> and <code class="literal">remove()</code> to the <code class="literal">Set
</code>interface. You can retrieve subsets (which are also sorted)
using the <a id="I_indexterm11_id742582" class="indexterm"/><code class="literal">subSet()</code>, <a id="I_indexterm11_id742593" class="indexterm"/><code class="literal">headSet()</code>, and
<a id="I_indexterm11_id742603" class="indexterm"/><code class="literal">tailSet()</code> methods.
These methods accept one or a pair of elements that mark the
boundaries. The <a id="I_indexterm11_id742615" class="indexterm"/><code class="literal">first()</code>, <a id="I_indexterm11_id742625" class="indexterm"/><code class="literal">last()</code>, and
<a id="I_indexterm11_id742636" class="indexterm"/><code class="literal">comparator()</code> methods
provide access to the first element, the last element, and the object
used to compare elements (more on this later).</p><p>Java 7 adds <code class="literal">NavigableSet</code>,
which extends <code class="literal">SortedSet</code> and adds
methods for finding the closest match greater or lesser than a target
value within the sort order of the <code class="literal">Set</code>. This interface can be implemented
efficiently using techniques such as skip lists, which make finding
ordered elements fast (Java 7 supplies such an implementation, which
we’ll note later).</p></div><div class="sect3" title="List"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.3.2"/>List</h3></div></div></div><p><a id="idx10598" class="indexterm"/> <a id="idx10649" class="indexterm"/>The next child interface of <code class="literal">Collection</code> is <code class="literal">List</code>. The <code class="literal">List</code> is an ordered collection, similar to an
array but with methods for manipulating the position of elements in
the list:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public boolean add( E</code>
<em class="replaceable"><code>element</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id742738" class="indexterm"/>This method adds the specified element to the end
of the list.</p></dd><dt><span class="term"><code class="literal">public void add( int</code>
<em class="replaceable"><code>index</code></em> <code class="literal">,
E</code> <em class="replaceable"><code>element</code></em> <code class="literal">)</code></span></dt><dd><p>This method inserts the given object at the supplied
position in the list. If the position is less than zero or
greater than the list length, an <code class="literal">IndexOutOfBoundsException</code> will be
thrown. The element that was previously at the supplied
position, and all elements after it, are moved up one index
position.</p></dd><dt><span class="term"><code class="literal">public void remove( int</code>
<em class="replaceable"><code>index</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id742799" class="indexterm"/>This method removes the element at the specified
position. All subsequent elements move down one index
position.</p></dd><dt><span class="term"><code class="literal">public E get( int</code>
<em class="replaceable"><code>index</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id742826" class="indexterm"/>This method returns the element at the given
position.</p></dd><dt><span class="term"><code class="literal">public Object set( int</code>
<em class="replaceable"><code>index</code></em> <code class="literal">,
E</code> <em class="replaceable"><code>element</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id742861" class="indexterm"/>This method changes the element at the given
position to the specified object. There must already be an
object at the index or else an <code class="literal">IndexOutOfBoundsException</code> is
thrown.</p></dd></dl></div><p>The type <code class="literal">E</code> in these methods
refers to the parameterized element type of the <code class="literal">List</code> class. <code class="literal">Collection</code>, <code class="literal">Set</code>, and <code class="literal">List</code> are all interface types. We’ll look at
concrete implementations of these shortly.<a id="I_indexterm11_id742905" class="indexterm"/><a id="I_indexterm11_id742912" class="indexterm"/></p></div><div class="sect3" title="Queue"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.3.3"/>Queue</h3></div></div></div><p><a id="I_indexterm11_id742926" class="indexterm"/> A <a id="I_indexterm11_id742937" class="indexterm"/><code class="literal">Queue</code> is a collection
that acts like a buffer for elements. The queue maintains the
insertion order of items placed into it and has the notion of a “head”
item. Queues may be first in, first out (FIFO) or last in, first out
(LIFO) depending on the implementation:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public boolean offer( E element
)</code><br/></span><span class="term"><code class="literal">public boolean add( E element
)</code></span></dt><dd><p>The <a id="I_indexterm11_id742969" class="indexterm"/><code class="literal">offer()</code> method
attempts to place the element into the queue, returning true if
successful. Different <code class="literal">Queue</code>
types may have different limits or restrictions on element types
(including capacity). This method differs from the <a id="I_indexterm11_id742987" class="indexterm"/><code class="literal">add()</code> method
inherited from <code class="literal">Collection</code> in
that it returns a Boolean value instead of throwing an exception
to indicate that the element cannot be accepted.</p></dd><dt><span class="term"><code class="literal">public E</code> <code class="literal">poll()</code><br/></span><span class="term"><code class="literal">public E remove()</code></span></dt><dd><p>The <a id="I_indexterm11_id743027" class="indexterm"/><code class="literal">poll()</code> method
removes the element at the head of the queue and returns it.
This method differs from the <code class="literal">Collection</code> method <a id="I_indexterm11_id743044" class="indexterm"/><code class="literal">remove()</code> in
that if the queue is empty, <code class="literal">null</code> is returned instead of throwing
an exception.</p></dd><dt><span class="term"><code class="literal">public E</code> <code class="literal">peek()</code></span></dt><dd><p><a id="I_indexterm11_id743076" class="indexterm"/>This method returns the head element
<span class="emphasis"><em>without</em></span> removing it from the queue. If the
queue is empty, <code class="literal">null</code> is
returned.</p></dd></dl></div><p>Java 7 added <a id="I_indexterm11_id743094" class="indexterm"/><code class="literal">Deque</code>, which is a
“double-ended” queue that supports adding, querying, and removing
elements from either end of the queue (the head or the tail). <code class="literal">Dequeue</code> has versions of the queue
methods—<code class="literal">offer</code>, <code class="literal">poll</code>, and <code class="literal">peek</code>—that operate on the first or last
element: <a id="I_indexterm11_id743130" class="indexterm"/><code class="literal">offerFirst()</code>,
<a id="I_indexterm11_id743141" class="indexterm"/><code class="literal">pollFirst()</code>,
<a id="I_indexterm11_id743151" class="indexterm"/><code class="literal">peekFirst()</code>,
<a id="I_indexterm11_id743162" class="indexterm"/><code class="literal">offerLast()</code>,
<a id="I_indexterm11_id743173" class="indexterm"/><code class="literal">pollLast()</code>,
<a id="I_indexterm11_id743183" class="indexterm"/><code class="literal">peekLast()</code>. Note that
<code class="literal">Deque</code> extends <code class="literal">Queue</code> and so is still a type of <code class="literal">Queue</code>. If you use the plain <code class="literal">Queue</code> methods <code class="literal">offer()</code>, <a id="I_indexterm11_id743221" class="indexterm"/><code class="literal">poll()</code>, and
<a id="I_indexterm11_id743231" class="indexterm"/><code class="literal">peek()</code> on a <code class="literal">Deque</code>, they operate as a FIFO queue.
Specifically, calling <code class="literal">offer()</code> is
equivalent to <code class="literal">offerLast()</code> and
calling <code class="literal">poll()</code> or <code class="literal">peek()</code> is the same as calling <code class="literal">pollFirst()</code> or <code class="literal">peekFirst()</code>, respectively.</p><p>Finally, Java has a legacy <a id="I_indexterm11_id743282" class="indexterm"/><code class="literal">Stack</code> class that acts
as a LIFO queue with “push” and “pop” operations, but <code class="literal">Deque</code> is generally better and should serve
as a general replacement for <code class="literal">Stack</code>.
Simply use <a id="I_indexterm11_id743306" class="indexterm"/><code class="literal">addFirst()</code> for “push”
and <code class="literal">pollFirst()</code> for “pop.”</p></div><div class="sect3" title="BlockingQueue"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.3.4"/>BlockingQueue</h3></div></div></div><p><a id="I_indexterm11_id743329" class="indexterm"/> <a id="I_indexterm11_id743340" class="indexterm"/> <code class="literal">BlockingQueue</code> is
part of the <a id="I_indexterm11_id743353" class="indexterm"/><code class="literal">java.util.concurrent</code>
package. It extends the <code class="literal">Queue</code>
interface for queues that may have a fixed capacity or other
time-based limitations and allows the user to block, waiting for
insertion of an item or for an available item to retrieve. It adds
timed wait versions of <a id="I_indexterm11_id743372" class="indexterm"/><code class="literal">offer()</code> and
<a id="I_indexterm11_id743382" class="indexterm"/><code class="literal">poll()</code> and
additional, blocking <a id="I_indexterm11_id743393" class="indexterm"/><code class="literal">take()</code> and <a id="I_indexterm11_id743403" class="indexterm"/><code class="literal">put()</code> methods:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public boolean offer( E element,
long time, TimeUnit units )</code></span></dt><dd><p>This method attempts to place the element into the queue,
just like the method of the base <code class="literal">Queue</code> interface, but blocks for up to
the specified period of time as it waits for space to become
available.</p></dd><dt><span class="term"><code class="literal">public E poll( long time, timeUnit
unit )</code></span></dt><dd><p>This method attempts to remove the element at the head of
the queue, just like the method of the base <code class="literal">Queue</code> interface, but blocks for up to
the specified period of time as it waits for an element to
become available.</p></dd><dt><span class="term"><code class="literal">public E take()</code></span></dt><dd><p>This method retrieves the element at the head of the
queue, blocking if necessary until one becomes available.</p></dd><dt><span class="term"><code class="literal">public void put( E element
)</code></span></dt><dd><p>This method adds an element to the queue, blocking if
necessary until space becomes available.</p></dd><dt><span class="term"><code class="literal">public boolean add( E element
)</code></span></dt><dd><p>This method attempts to add an element to the queue
immediately. If successful, it returns <code class="literal">true</code>. If no space is available, it
throws an <a id="I_indexterm11_id743488" class="indexterm"/><code class="literal">IllegalStateException</code>. This method is
useful for cases where you are not expecting the queue to ever
reject an item.<a id="I_indexterm11_id743501" class="indexterm"/></p></dd></dl></div></div></div><div class="sect2" title="The Map Interface"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-11-SECT-4.4"/>The Map Interface</h2></div></div></div><p><a id="idx10606" class="indexterm"/> <a id="idx10618" class="indexterm"/> <a id="idx10658" class="indexterm"/>The Collections Framework also includes the <code class="literal">java.util.Map</code>, which is a collection of
key/value pairs. Other names for map are “dictionary” or “associative
array.” Maps store and retrieve elements with key values; they are very
useful for things like caches or minimalist databases. When you store a
value in a map, you associate a key object with a value. When you need
to look up the value, the map retrieves it using the key.</p><p>With generics, a <code class="literal">Map</code> type is
parameterized with two types: one for the keys and one for the values.
The following snippet uses a <code class="literal">HashMap</code>,
which is an efficient type of map implementation that we’ll discuss
later:</p><a id="I_11_tt714"/><pre class="programlisting"> <code class="n">Map</code><code class="o"><</code><code class="n">String</code><code class="o">,</code> <code class="n">Date</code><code class="o">></code> <code class="n">dateMap</code> <code class="o">=</code> <code class="k">new</code> <code class="n">HashMap</code><code class="o"><</code><code class="n">String</code><code class="o">,</code> <code class="n">Date</code><code class="o">>();</code>
<code class="n">dateMap</code><code class="o">.</code><code class="na">put</code><code class="o">(</code> <code class="s">"today"</code><code class="o">,</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">);</code>
<code class="n">Date</code> <code class="n">today</code> <code class="o">=</code> <code class="n">dateMap</code><code class="o">.</code><code class="na">get</code><code class="o">(</code> <code class="s">"today"</code> <code class="o">);</code></pre><p>In legacy code, maps simply map <code class="literal">Object</code> types to <code class="literal">Object</code> types and require the appropriate cast
to retrieve values.</p><p>The basic operations on <code class="literal">Map</code> are
straightforward. In the following methods, the type <code class="literal">K</code> refers to the key parameter type and the
type <code class="literal">V</code> refers to the value parameter
type:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public V put( K</code>
<em class="replaceable"><code>key</code></em> <code class="literal">,
V</code> <em class="replaceable"><code>value</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id743650" class="indexterm"/>This method adds the specified key/value pair to the
map. If the map already contains a value for the specified key,
the old value is replaced and returned as the result.</p></dd><dt><span class="term"><code class="literal">public V get( K</code>
<em class="replaceable"><code>key</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id743675" class="indexterm"/>This method retrieves the value corresponding to
<code class="literal">key</code> from the map.</p></dd><dt><span class="term"><code class="literal">public V remove( K</code>
<em class="replaceable"><code>key</code></em> <code class="literal">)</code></span></dt><dd><p><a id="I_indexterm11_id743706" class="indexterm"/>This method removes the value corresponding to
<code class="literal">key</code> from the map. The value
removed is returned.</p></dd><dt><span class="term"><code class="literal">public int size()</code></span></dt><dd><p><a id="I_indexterm11_id743730" class="indexterm"/>Use this method to find the number of key/value
pairs in this map.</p></dd></dl></div><p>You can retrieve all the keys or values in the map:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public Set keySet()</code></span></dt><dd><p><a id="I_indexterm11_id743751" class="indexterm"/>This method returns a <code class="literal">Set</code> that contains all the keys in this
map.</p></dd><dt><span class="term"><code class="literal">public Collection
values()</code></span></dt><dd><p><a id="I_indexterm11_id743773" class="indexterm"/>Use this method to retrieve all the values in this
map. The returned <code class="literal">Collection</code>
can contain duplicate elements.</p></dd></dl></div><p><code class="literal">Map</code> has one child interface,
<a id="I_indexterm11_id743792" class="indexterm"/><code class="literal">SortedMap</code>. A <code class="literal">SortedMap</code> maintains its key/value pairs sorted
in a particular order according to the key values. It provides the
<a id="I_indexterm11_id743809" class="indexterm"/><code class="literal">subMap()</code>, <a id="I_indexterm11_id743820" class="indexterm"/><code class="literal">headMap()</code>, and
<a id="I_indexterm11_id743830" class="indexterm"/><code class="literal">tailMap()</code> methods for
retrieving sorted map subsets. Like <a id="I_indexterm11_id743841" class="indexterm"/><code class="literal">SortedSet</code>, it also
provides a <code class="literal">comparator()</code> method, which
returns an object that determines how the map keys are sorted. We’ll
talk more about that later. Java 7 adds a <a id="I_indexterm11_id743860" class="indexterm"/><code class="literal">NavigableMap</code> with
functionality parallel to that of <code class="literal">NavigableSet</code>; namely, it adds methods to
search the sorted elements for an element greater or lesser than a
target value.</p><p>Finally, we should make it clear that although related, <code class="literal">Map</code> is not literally a type of <code class="literal">Collection</code> (<code class="literal">Map</code> does not extend the <code class="literal">Collection</code> interface). You might wonder why.
All of the methods of the <code class="literal">Collection</code>
interface would appear to make sense for <code class="literal">Map</code>, except for <code class="literal">iterator()</code>. A <code class="literal">Map</code>, again, has two sets of objects: keys and
values, and separate iterators for each. This is why a <code class="literal">Map</code> does not implement <code class="literal">Collection</code>.</p><p>One more note about maps: some map implementations (including
Java’s standard <code class="literal">HashMap</code>) allow
<code class="literal">null</code> to be used as a key or value,
but others may not.</p><div class="sect3" title="ConcurrentMap"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-11-SECT-4.4.1"/>ConcurrentMap</h3></div></div></div><p><a id="idx10610" class="indexterm"/>The <code class="literal">ConcurrentMap</code>
interface is part of the <code class="literal">java.util.concurrent</code> package. It extends the
base <code class="literal">Map</code> interface and adds atomic
put, remove, and replace functionality that is useful for concurrent
programming:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">public V putIfAbsent( K key, V
value )</code></span></dt><dd><p><a id="I_indexterm11_id743996" class="indexterm"/>This method associates the value with the key only
if the key was not already in use. If the key exists, no action
is taken. If the key does not exist, it is created. The
resulting value (<code class="literal">existing</code> or
<code class="literal">new</code>) is returned.</p></dd><dt><span class="term"><code class="literal">public boolean remove( Object key,
Object value )</code></span></dt><dd><p><a id="I_indexterm11_id744024" class="indexterm"/>This method removes the mapping (key and value)
only if the current value associated with the key equals the
supplied value. It returns <code class="literal">true</code> if the value was removed,
<code class="literal">fals