Home of The JavaSpecialists' Newsletter

140Book Review: Java Generics and Collections

Posted: 2007-03-08Category: Book ReviewJava Version: 1.5+Dr. Heinz M. Kabutz

Abstract: Java Generics and Collections is the "companion book" to The Java Specialists' Newsletter. A well written book that explains generics really nicely, including some difficult concepts. In addition, they cover all the new collection classes up to Java 6 Mustang.


Welcome to the 140th edition of The Java(tm) Specialists' Newsletter, now sent to 113 countries with the recent addition of Jordan. This morning, my wife Helene, our baby Evangeline and I went for a lovely walk on Kalathas Beach, a versatile and wholly pleasant beach, close to where we live. The sand is soft, the water shallow (perfect for kids) but gets deeper after a while (perfect for dad). There is a rocky outcrop a bit further out, from which you can jump into the water. There are more fish than at other beaches. They have a fantastic restaurant on the beach that serves genuine Cretan cooking. It is a great all-round beach :) Here are some pictures of Kalathas Beach: http://www.javaspecialists.eu/crete/kalathas.jsp.

NEW: Refactoring to Java 8 Lambdas and Streams Workshop Are you currently using Java 6 or 7 and would like to see how Java 8 can improve your code base? Are you tired of courses that teach you a whole bunch of techniques that you cannot apply in your world? Check out our one day intensive Refactoring to Java 8 Lambdas and Streams Workshop.

Book Review: Java Generics and Collections

The companion book to The Java(tm) Specialists' Newsletter!

Occasionally, books are written that appeal to Java specialists (unfortunately not often enough). Java Generics and Collections is such a book. Here are some fascinating nuggets that I found - there are many more.

Explicit Parameters

Mixing generic methods and varargs produces some side effects that result in strange syntax, which most Java programmers don't know. Let's start with the following class:

import java.util.*;

public class Lists {
  public static <T> List<T> toList(T... arr) {
    List<T> list = new ArrayList<T>();
    for (T t : arr) list.add(t);
    return list;

We can now use this to produce lists of ints or Strings:

List<Integer> ints = Lists.toList(1, 2, 3);
List<String> words = Lists.toList("hello", "world");

At runtime, the arguments are packed into an array, which is passed to the method toList().

Now comes the catch: What is the generic type that comes back when you pass different types of objects to the toList() method, for example:

List<?> something = Lists.toList("one", 2, 3.0);

You would expect that you can simply write:

List<Object> objects = Lists.toList("one", 2, 3.0); // does not compile!

However, this is not possible, since there is a lower common class, in this case java.io.Serializable. If you want to bind T to a particular class, for example Object, you need to use explicit parameters:

List<Object> objects = Lists.<Object>toList("one", 2, 3.0);

You cannot mix explicit parameters with static imports. The Java grammar requires that type parameters may appear only in method invocations that use a dotted form.

Although I am certain this appears in other publications, this book is the first place I read such a clear explanation.

Migrating Legacy Code

In chapter 5: "Evolution, Not Revolution", we see various approaches we can use when migrating from legacy code to generics.

Migrating is migrane and grating rolled into one!

They offer various solutions for legacy and generic clients and libraries combinations. The most interesting combination is where you have a legacy library and a generic client. There are various alternatives:

  1. Evolving a library using minimal changes: Change the method declarations, but keep the actual code the same. Use a generous helping of @SuppressWarnings("unchecked) annotations. We can only do that if we have access to the source.
  2. Evolving a library using stubs: Write stubs with generic signatures but no bodies. We compile the generic client against the generic signatures, but run the code against the legacy class files. We can do that when we do not have access to the source.
  3. Evolving a library using wrappers: Here we leave the legacy source and class files unchanged, and provide a wrapper class that accesses the legacy class via delegation. This is actually an anti-pattern and brings with it many problems. In the book they warn you against its use.

The book then continues by describing reification and the effects this has. After that comes reflection with generics. Both are interesting chapters for Java specialists.

Design Patterns & Generics

In chapter 9, we see several design patterns implemented with generics, including our popular strategy pattern newsletter, which is reprinted in the book (with permission). They also show the Visitor, Interpreter, Function and Observer patterns.


The book then goes on to Java 5 and Java 6 collections, including the latest Deque and NavigableMap classes.

Each collection chapter ends with a table of big O notation for each operations. This is only meant as a guideline in deciding which implementation to choose. TreeMap can quite easily outperform HashMap depending on the complexity of the hashCode(), equals() and compareTo() methods.

Regular and Jumbo EnumSet

One area that the book did not pick up on is the significance of the EnumSet.noneOf() method. This is actually a factory method that returns different implementations of EnumSet depending on the key universe. If the key universe is larger than 64, it creates a JumboEnumSet, if it is smaller, a RegularEnumSet. The JumboEnumSet represents the bitset as a long[], whereas the RegularEnumSet simply contains a long. I suspect that the authors felt this going too deep into implementation details.

import java.util.EnumSet;

public class EnumSetTest {
  public enum SMALL {
    A0, A1, A2

  public enum MEDIUM {
    A00, A01, A02, A03, A04, A05, A06, A07, A08, A09,
    A10, A11, A12, A13, A14, A15, A16, A17, A18, A19,
    A20, A21, A22, A23, A24, A25, A26, A27, A28, A29,
    A30, A31, A32, A33, A34, A35, A36, A37, A38, A39,
    A40, A41, A42, A43, A44, A45, A46, A47, A48, A49,
    A50, A51, A52, A53, A54, A55, A56, A57, A58, A59,
    A60, A61, A62, A63

  public enum LARGE {
    A00, A01, A02, A03, A04, A05, A06, A07, A08, A09,
    A10, A11, A12, A13, A14, A15, A16, A17, A18, A19,
    A20, A21, A22, A23, A24, A25, A26, A27, A28, A29,
    A30, A31, A32, A33, A34, A35, A36, A37, A38, A39,
    A40, A41, A42, A43, A44, A45, A46, A47, A48, A49,
    A50, A51, A52, A53, A54, A55, A56, A57, A58, A59,
    A60, A61, A62, A63, A64

  public static void main(String[] args) {

When we run this, we see as output:

    class java.util.RegularEnumSet
    class java.util.RegularEnumSet
    class java.util.JumboEnumSet

The book has a lot more fascinating information about generics and collections than I could describe in one newsletter.

If possible, please consider supporting the authors by purchasing the book, and not downloading the PDF from the internet somewhere :-)

Kind regards from Europe


P.S. Have you already bought the book? Let me know if you liked it (or not)!


Related Articles

Browse the Newsletter Archive

About the Author


Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

Nobody ever wants to call a Java performance consultant, but with first-hand experience repairing and improving commercial Java applications - JavaSpecialists are a good place to start...

Threading Emergency?

If your system is down, we will review it for 15 minutes and give you our findings for just 1 € without any obligation.