The Collections Framework in Java, which took shape with the release of JDK 1.2 and was expanded in 1.4 and again in Java 5, and yet again in Java 6, gives you Lists, Sets, Maps and Queues to satisfy most of your coding needs. They've been tried, tested, and tweaked. Pick the best one for your job and you will get at the least reasonable performance. And when you need something a little more custom, the Collections Framework in the java.util package is loaded with interfaces and utilities.
There are a few basic operations you'll normally use with collections :
| 1 | Add objects to the collection. |
| 2 | Remove objects from the collection. |
| 3 | Retrieve an object from the collection (without removing it) |
| 4 | Find out if an object (or group of objects) is in the collection. |
| 5 | Iterate through the collection, looking at each element (object) one after another. |
The collections API begins with a group of interfaces, but also gives you a truckload of concrete classes. The core interfaces you need to know for the developments are the following Nine :
| Collection | Set | SortedSet |
| List | Map | SortedMap |
| Queue | NavigableSet | NavigableMap |
The core concrete implementation classes you need to know for the developments are the following Thirteen :
| Map | Set | List | Queues | Utilities |
|---|---|---|---|---|
| HashMap | HashSet | ArrayList | PriorityQueue | Collections |
| Hashtable | LinkedHashSet | Vector | Arrays | |
| TreeMap | TreeSet | LinkedList | ||
| LinkedHashMap |
There are really three overloaded uses of the word " Collection " :
| 1 | collection (Lowercase c) , which represents any of the data structures in which objects are stored and iterated over. |
| 2 | Collection (Capital C) , which is actually the java.util.Collection interface from which Set, List, and Queue extend. (That is right, extend, not implement. There are no direct implementations of Collection.) |
| 3 | Collections (Capital C and ends with s) is the java.util.Collections class that holds a pile of static utility methods for use with collections. |
Collections come in four basic flavors :
| Lists | Lists of things (classes that implement List). |
| Sets | Unique things (classes that implement Set). |
| Maps | Things with a unique ID (classes that implement Map). |
| Queues | Things arranged by the order in which they are to be processed. |
But there are Sub Flavors within those four flavors of collections :
| Sorted | Unsorted | Ordered | Unordered |
A List cares about the index. The one thing that List has that non-lists don't have is a set of methods related to the index. All three List implementations are ordered by index position—a position that you determine either by setting an object at a specific index or by adding it without specifying position, in which case the object is added to the end. The three List implementations are described in the following sections.
1. ArrayList : ArrayList gives you fast iteration and fast random access. To state the obvious: it is an ordered collection (by index), but not sorted. You might want to know that as of version 1.4, ArrayList now implements the new RandomAccess interface—a marker interface (meaning it has no methods) that says, "this list supports fast (generally constant time) random access." Choose this over a LinkedList when you need fast iteration but aren't as likely to be doing a lot of insertion and deletion.
2. Vector : Vector is a holdover from the earliest days of Java; Vector and Hashtable were the two original collections, the rest were added with Java 2 versions 1.2 and 1.4. A Vector is basically the same as an ArrayList, but Vector methods are synchronized for thread safety. You'll normally want to use ArrayList instead of Vector because the synchronized methods add a performance hit you might not need. And if you do need thread safety, there are utility methods in class Collections that can help. Vector is the only class other than ArrayList to implement RandomAccess.
3. LinkedList : A LinkedList is ordered by index position, like ArrayList, except that the elements are doubly-linked to one another. This linkage gives you new methods (beyond what you get from the List interface) for adding and removing from the beginning or end, which makes it an easy choice for implementing a stack or queue. Keep in mind that a LinkedList may iterate more slowly than an ArrayList, but it's a good choice when you need fast insertion and deletion. As of Java 5, the LinkedList class has been enhanced to implement the java.util.Queue interface. As such, it now supports the common queue methods: peek(), poll(), and offer().
A Set cares about uniqueness—it doesn't allow duplicates. Your good friend the equals() method determines whether two objects are identical (in which case only one can be in the set). The three Set implementations are described in the following sections.
1. HashSet : A HashSet is an unsorted, unordered Set. It uses the hashcode of the object being inserted, so the more efficient your hashCode() implementation the better access performance you'll get. Use this class when you want a collection with no duplicates and you don't care about order when you iterate through it.
2. LinkedHashSet : A LinkedHashSet is an ordered version of HashSet that maintains a doubly-linked List across all elements. Use this class instead of HashSet when you care about the iteration order. When you iterate through a HashSet theorder is unpredictable, while a LinkedHashSet lets you iterate through the elements in the order in which they were inserted.
3. TreeSet : The TreeSet is one of two sorted collections (the other being TreeMap). It uses a Red-Black tree structure (but you knew that), and guarantees that the elements will be in ascending order, according to natural order. Optionally, you can construct a TreeSet with a constructor that lets you give the collection your own rules for what the order should be (rather than relying on the ordering defined by the elements' class) by using a Comparable or Comparator. As of Java 6, TreeSet implements NavigableSet.
A Map cares about unique identifiers. You map a unique key to a specific value, where both the key and the value are, of course, objects. You're probably quite familiar with Maps since many languages support data structures that use a key/value or name/value pair. The Map implementations let you do things like search for a value based on the key, ask for a collection of just the values, or ask for a collection of just the keys. Like Sets, Maps rely on the equals() method to determine whether two keys are the same or different.
1. HashMap : The HashMap gives you an unsorted, unordered Map. When you need a Map and you don't care about the order (when you iterate through it), then HashMap is the way to go; the other maps add a little more overhead. Where the keys land in the Map is based on the key's hashcode, so, like HashSet, the more efficient your hashCode() implementation, the better access performance you'll get. HashMap allows one null key and multiple null values in a collection.
2. Hashtable : Hashtable has existed from prehistoric Java times. For fun, don't forget to note the naming inconsistency: HashMap vs. Hashtable. Where's the capitalization of t? Oh well, you won't be expected to spell it. Anyway, just as Vector is a synchronized counterpart to the sleeker, more modern ArrayList, Hashtable is the synchronized counterpart to HashMap. Remember that you don't synchronize a class, so when we say that Vector and Hashtable are synchronized, we just mean that the key methods of the class are synchronized. Another difference, though, is that while HashMap lets you have null values as well as one null key, a Hashtable doesn't let you have anything that's null.
3. LinkedHashMap : The LinkedHashMap collection maintains insertion order (or, optionally, access order). Although it will be somewhat slower than HashMap for adding and removing elements, you can expect faster iteration with a LinkedHashMap.
4. TreeMap : A TreeMap is a sorted Map and you already know that by default, this means "sorted by the natural order of the elements." Like TreeSet, TreeMap lets you define a custom sort order (via a Comparable or Comparator) when you construct a TreeMap, that specifies how the elements should be compared to one another when they're being ordered. As of Java 6, TreeMap implements NavigableMap.
A Queue is designed to hold a list of "to-dos," or things to be processed in some way. Although other orders are possible, queues are typically thought of as FIFO (First In First Out). Queues support all of the standard Collection methods and they also add methods to add and subtract elements and review queue elements.
1. PriorityQueue : This class is new with Java 5. Since the LinkedList class has been enhanced to implement the Queue interface, basic queues can be handled with a LinkedList. The purpose of a PriorityQueue is to create a "Priority In, Priority Out" queue as opposed to a typical FIFO (First In First Out) Queue. A PriorityQueue's elements are ordered either by natural ordering (in which case the elements that are sorted first will be accessed first) or according to a Comparator. In either case, the elements' ordering represents their relative priority.
| Class | Map | Set | List | Queue | Ordered | Sorted |
|---|---|---|---|---|---|---|
| HashMap | X | No | No | |||
| Hashtable | X | No | No | |||
| TreeMap | X | Sorted | By Natural Order/Custom Comparison Rules | |||
| LinkedHashMap | X | By Insertion Order/Last Access Order | No | |||
| HashSet | X | No | No | |||
| LinkedHashSet | X | No | No | |||
| TreeSet | X | Sorted | By Natural Order/Custom Comparison Rules | |||
| ArrayList | X | By Insertion Order | No | |||
| Vector | X | No | No | |||
| LinkedList | X | No | No | |||
| PriorityQueue | X | Sorted | By to-do order |