More generics hacks

Continuing on the generics discussion here, I’ve been using a pattern that I’ve seen discussed in the blogosphere to reduce redundancy in creating collections, e.g. some utility methods on a CollectionUtils class:

public static <T> ArrayList<T> newArrayList() {
  return new ArrayList<T>();
}

public static <T> HashSet<T> newHashSet() {
  return new HashSet<T>();
}

public static <K, V> HashMap<K, V> newHashMap() {
  return new HashMap<K, V>();
}

This eliminates the redundancy of specifying the type(s) twice:

List<VerboseTypeName> list = new ArrayList<VerboseTypeName>();

Map<VerboseKeyName, VerboseValueName> map =
        new HashMap<VerboseKeyName, VerboseValueName>();

becomes

List<VerboseTypeName> list = newArrayList();

Map<VerboseKeyName, VerboseValueName> map = newHashMap();

assuming we use static imports for the utility methods.

But Groovy and other scripting languages are making me realize how unnecessarily verbose Java is. For example, in Groovy I can create a List and initialize its elements in one line:

def numbers = [1, 1, 2, 3, 5, 8, 13, 21];

I recently realized that I can use VarArgs and amend the utility methods to take optional initializing values:

public static <T> ArrayList<T> newArrayList(final T... elements) {
  return new ArrayList<T>(Arrays.asList(elements));
}

public static <T> HashSet<T> newHashSet(final T... elements) {
  return new HashSet<T>(Arrays.asList(elements));
}

and then

List<String> strings = new ArrayList<String>();
strings.add("foo");
strings.add("bar");
strings.add("baz");

becomes

List<String> strings = newArrayList("foo", "bar", "baz");

Of course this isn’t new – for example Hibernate Shards has a similar implementation but with the various methods split by interface.

7 Responses to “More generics hacks”

  1. Peter Lawrey says:

    Another trick in this line is

    {code}
    public static Map newMap(K key, V value, Object… keyValues) {
    Map ret = new LinkedHashMap();
    ret.put(key, value);
    for(int i = 0; i

  2. Peter Lawrey says:

    hmmm perhaps html is enabled?

    public static Map newMap(K key, V value, Object… keyValues) {
    Map ret = new LinkedHashMap();
    ret.put(key, value);
    for(int i = 0; i > keyValues.length; i += 2)
    ret.put((K) keyValues[i], (V) keyValues[i+1]);
    return ret;
    }

  3. Peter Lawrey says:

    That should be less than <

  4. Peter Lawrey says:

    one last try, having preview would help….

    public static Map<K, V> newMap(K key, V value, Object… keyValues) {
    Map<K, V> ret = new LinkedHashMap<K, V>();
    ret.put(key, value);
    for(int i = 0; i < keyValues.length; i += 2)
    ret.put((K) keyValues[i], (V) keyValues[i+1]);
    return ret;
    }

  5. Burt says:

    That is pretty cool – I couldn’t think of a clean way to pre-populate a Map like you can for a List or Set (since you can only have one vararg parameter) but this does the trick.

  6. […] More fun with Generics – Class.cast() digg_url = ‘http://burtbeckwith.com/blog/?p=50’; digg_title = ‘More fun with Generics – Class.cast()’; digg_bodytext = ‘Continuing the discussion from here and here. We’ve been making extensive use of generics at work and in the process have discovered a bug in the 1.6 JDK (more on that later). The problem is that we can’t cast to the actual type of some generic instance variables, and also can’t use instanceof. The annoying thing […]’; digg_topic = “programming”; ( function() { var ds=typeof digg_skin==’string’?digg_skin:”; var h=80; var w=52; if(ds==’compact’) { h=18; w=120; } var u=typeof digg_url==’string’?digg_url:(typeof DIGG_URL==’string’?DIGG_URL:window.location.href); document.write(“”); } )() Continuing the discussion from here and here. […]

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.