Printing containers
Unlike arrays, the containers print nicely without any help. Here’s an example that also introduces you to the basic types of containers:
//: c11:PrintingContainers.java
// Containers print themselves automatically.
import com.bruceeckel.simpletest.*;
import java.util.*;
public class PrintingContainers {
private static Test monitor = new Test();
static Collection fill(Collection c) {
c.add("dog");
c.add("dog");
c.add("cat");
return c;
}
static Map fill(Map m) {
m.put("dog", "Bosco");
m.put("dog", "Spot");
m.put("cat", "Rags");
return m;
}
public static void main(String[] args) {
System.out.println(fill(new ArrayList()));
System.out.println(fill(new HashSet()));
System.out.println(fill(new HashMap()));
monitor.expect(new String[] {
"[dog, dog, cat]",
"[dog, cat]",
"{dog=Spot, cat=Rags}"
});
}
} ///:~
As mentioned before, there are two basic categories in the Java container library. The distinction is based on the number of items that are held in each location of the container. The Collection category only holds one item in each location (the name is a bit misleading, because entire container libraries are often called “collections”). It includes the List, which holds a group of items in a specified sequence, and the Set, which only allows the addition of one item of each type. The ArrayList is a type of List, and HashSet is a type of Set. To add items to any Collection, there’s an add( ) method.
The Map holds key-value pairs, rather like a mini database. The preceding example uses one flavor of Map, the HashMap. If you have a Map that associates states with their capitals and you want to know the capital of Ohio, you look it up—almost as if you were indexing into an array. (Maps are also called associative arrays.) To add elements to a Map, there’s a put( ) method that takes a key and a value as arguments. The example only shows adding elements and does not look up the elements after they’re added. That will be shown later.
The overloaded fill( ) methods fill Collections and Maps, respectively. If you look at the output, you can see that the default printing behavior (provided via the container’s various toString( ) methods) produces quite readable results, so no additional printing support is necessary as it was with arrays. A Collection is printed surrounded by square brackets, with each element separated by a comma. A Map is surrounded by curly braces, with each key and value associated with an equal sign (keys on the left, values on the right).
You can also immediately see the basic behavior of the different containers. The List holds the objects exactly as they are entered, without any reordering or editing. The Set, however, only accepts one of each object, and it uses its own internal ordering method (in general, you are only concerned with whether or not something is a member of the Set, not the order in which it appears—for that you’d use a List). And the Map also only accepts one of each type of item, based on the key, and it also has its own internal ordering and does not care about the order in which you enter the items. If maintaining the insertion sequence is important, you can use a LinkedHashSet or LinkedHashMap.