When working with collection classes, work through interfaces
As with all Java programming, interfaces isolate implementation
details. By using interfaces, the programmer can easily refactor a
program to use a different collection implementation by changing only
the initialization code.
There is little performance benefit in using a nonsynchronized
collection
This may be surprising to many developers梖or an understanding
of the performance issues around lock acquisition, see Chapter 14. In brief, performance issues with lock
acquisitions occur only when there is contention for the lock.
However, a nonsynchronized collection should have no contention for
the lock. If there is contention, having race conditions is a more
problematic issue than performance.
For algorithms with a lot of contention, consider using the
concurrent collections
The set, hashmap, and
list collections that were added in J2SE
5.0 are highly optimized. If a program's algorithm
fits into one of these interfaces, consider choosing a J2SE 5.0
collection over a synchronized version of a JDK 1.2 collection. The
concurrent collections are much better optimized for multithreaded
access.
For producer/consumer-based programs, consider using a queue as the
collection
Queues are best for
the producer/consumer model for many
reasons. First, queues provide an ordering of requests, preventing
data starvation. Second, queues are highly optimized, having minimal
synchronization, atomic accesses, and even safe parallel access in
many cases. With these collections, a huge number of threads can work
in parallel with little bottlenecking at the queue's
access points.
When possible, try to minimize the use of explicit synchronization
Iterators and other support methods that require tranversal of an
entire collection may need more synchronization than the collection
provides alone. This can be a problem when many threads are involved.
Limit your use of iterators from the copy-on-write collections
First, use these classes only when the number of elements in the
collection is small. This is because of the time and size
requirements of the copy-on-write operation. Second, your
program must not require that the collection have the most up-to-date
information. The iterator contains only the information of the
collection at the time that it is created.
Consider using multiple collections
While some of these collections have minimal synchronization, these
synchronization periods can still be an issue when many threads are
involved. Consider having an algorithm that uses segmented
collections instead of a generic implementation in which all threads
use the same collection.
There is little difference between a set and a map
Theoretically, a set
and a map are different
in a number of ways, but in terms of implementation, there is little
difference. Many of the set collections are just implemented by using
the map collection. This means that the choice is not actually a
choice: an item stored in a set is merely stored as a key in a map.