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.
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
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;
}
That should be less than <
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;
}
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.
[…] 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. […]
Well, someone’s done the map thing … Building your own literals in Java – Tuples and Maps.