5/30/2006

Unnecessary Cast in Map

Unnecessary casts clog your code and slow down you applications. They may seem small individually, but if they are inside loops or frequent code paths, they do add up. One common unnecessary cast happens to java.util.Map key:

public static void unnecessaryCast() {

Map map = new HashMap();
map.put("language", "Java");

for(Iterator it = map.keySet().iterator(); it.hasNext();) {
//casting key to String is unnecessary for map lookup
String key = (String) it.next();

//casting to String is unnecessary for println
String val = (String) map.get(key);

System.out.println("key = " + key + ", value = " + val);
}
}
Casting (in red) for the map key is not needed for the purpose of calling java.util.Map.get(key), unless you also need a String type of key later.

Casting (in blue) for the map value is not needed for the purpose of System.out.println(value), unless you also need a String type of value later. JVM will correctly dispatch to String.toString() when you concatenate ", value = " to an java.lang.Object value.

So I would simply change the two lines to:
Object key = it.next();
Object val = map.get(key);

6 comments:

Anonymous said...

I agree that it's not needed and sloppy, but arguing that it's faster just doesn't make the argument.

I tried your code samples over 10 million iterations and was only able to notice a 10% improvement, and we're only really talking about a couple of milliseconds at that.

On the other hand, if you did it this way:

for(int i = 0; i < 10000000; i++) {
for(Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry)it.next();
}
}

You would notice a 25-30% increase.

howto said...

That's interesting to know. I guess entrySet is like a coarse-grained object while key and value are more fine-grained ones. So it's likely your solution is faster.

But using Map.Entry requires at least 3 steps to get key-value:

1. get Map.Entry;
2. get key from entry;
3. get value from entry.

Anonymous said...

It's not a matter of course grained or fined grained anything. It's the same data.

If you are trying to optimize at this level, you application has serious problems.

Eugene Kuleshov said...

It is usually always wrong to make assumptions about performance. You should always test it and measure. While I agree that an extra cast would increase size of the bytecode it also gives a hin to HotSpot compiller, so it can use this information and produce a slightly faster code. You can see that after warming up cast is faster then no cast, and yet entrySet is significantly faster (since it does not do lookup trough hash table)

cast 0 3.365
nocast 0 3.255
entry 0 3.004

cast 1 3.034
nocast 1 3.365
entry 1 3.225

cast 2 3.315
nocast 2 3.094
entry 2 2.874

cast 3 3.065
nocast 3 3.435
entry 3 2.844

cast 4 3.024
nocast 4 3.215
entry 4 2.854

Here is the code:

private static void withEntry(HashMap map, int j) {
long l1 = System.currentTimeMillis();

int n = 0;
for(int i = 0; i<K; i++) {
for(Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry e = (Entry) it.next();
Object k = e.getKey();
Object v = e.getValue();
n += v.hashCode() + k.hashCode();
}
}

long l2 = System.currentTimeMillis();
System.err.println("entry "+ j + " "+(l2-l1)/1000f);
}

private static void withoutCast(HashMap map, int j) {
long l1 = System.currentTimeMillis();

int n = 0;
for(int i = 0; i<K; i++) {
for(Iterator it = map.keySet().iterator(); it.hasNext();) {
Object l = it.next();
Object o = map.get(l);
n += o.hashCode();
}
}

long l2 = System.currentTimeMillis();
System.err.println("nocast "+ j + " "+(l2-l1)/1000f);
}

private static void withCast(HashMap map, int j) {
long l1 = System.currentTimeMillis();

int n = 0;
for(int i = 0; i<K; i++) {
for(Iterator it = map.keySet().iterator(); it.hasNext();) {
String l = (String) it.next();
Object o = map.get(l);
n += o.hashCode();
}

}
long l2 = System.currentTimeMillis();
System.err.println("cast " + j + " " + (l2 - l1) / 1000f);
}

howto said...

Regarding the assumption on performance, I couldn't agree with you more. I was being lazy not testing it out. Thanks for the comments and measuring.

Anna said...

Great and Useful Article.

Online Java Course

Java Online Training

Java Course Online

J2EE training

online J2EE training

Best Recommended books for Spring framework

Java Interview Questions












Java Training Institutes in Chennai

Java Training in Chennai

J2EE Training in Chennai

java j2ee training institutes in chennai