Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any fully generic version of Map.get(), i.e, "V get(K key)"

Tags:

java

generics

Since Map.get() is not fully generic, we often find cases where a developer passed a different type of object (and hence bugs). Frequency of such cases went up when we started using artifacts/services from other teams. What are the reasons why Map.get(Object key) is not (fully) generic explains why get() is not fully generic.

Since we don't really have use cases of two objects, belonging to different types, but 'semantically' being equal, having a version of Map.get() would really help us identify such bugs at compile time. Any APIs, that can be used in production, exist?

like image 983
Srini Avatar asked Sep 14 '11 15:09

Srini


3 Answers

This isn't a direct answer to your question, but some IDEs (at least IntelliJ) have an inspection to flag suspicious uses of collections, and this is definitely caught by it:

Map<String, Integer> map = new HashMap<String, Integer>();
map.put("hello", 5);

//In IntelliJ, this line gives the warning: 
//Map<String, Integer> may not contain objects of type StringBuilder
System.out.println(map.get(new StringBuilder("hello")));

You mentioned you were trying to catch these problems at compile time so I thought it was worth mentioning. You could pair this with a static analysis tool for your build server, such as findbugs.

In IntelliJ the inspection is called "Suspicious collections method calls".

Edit (2011/10/18)

In FindBugs it appears that the bug GC_UNRELATED_TYPES should catch this (though I haven't attempted to test this):

GC: No relationship between generic parameter and method argument

This call to a generic collection method contains an argument with an incompatible class from that of the collection's parameter (i.e., the type of the argument is neither a supertype nor a subtype of the corresponding generic type argument). Therefore, it is unlikely that the collection contains any objects that are equal to the method argument used here. Most likely, the wrong value is being passed to the method. (...)

like image 162
Mark Peters Avatar answered Oct 20 '22 02:10

Mark Peters


Here's a helper method that provides checked access:

public static <K, V> V safeGet(Map<? super K, ? extends V> map, K key) {
    return map.get(key);
}

Sample Usage:

Map<List<String>, Date> map = new HashMap<List<String>, Date>();
// this compiles:
Date date = safeGet(map, Arrays.asList(""));
// this doesn't
Date date2 = safeGet(map, "foo");
like image 27
Sean Patrick Floyd Avatar answered Oct 20 '22 04:10

Sean Patrick Floyd


FunctionalJava provides one: http://functionaljava.googlecode.com/svn/artifacts/3.0/javadoc/fj/data/HashMap.html

like image 1
John B Avatar answered Oct 20 '22 02:10

John B