简体   繁体   中英

Is it more efficient to use the class, e.g. Hashtable than the interface, e.g. Map?

Will the compiler generate better code if it knows the actual class it will be working with vs the interface?

For example, I refer to my actual class like so:

Hashtable<String,String> foo() {
    Hashtable<String,String> table = new Hashtable<String,String>(100);
    ....
    return table;
}

...

    Hashtable<String,String> tbl = foo();

VS

Map<String,String> foo() {
    Map<String,String> table = new Hashtable<String,String>(100);
    ....
    return table;
}

...

    Map<String,String> tbl = foo();

Will the first form be more efficient?


OK, summarizing the answers now. I wish I could mark both Thomas and Tagir as correct, but I can't.

Thomas is correct in that the "correct" behavior is to use the abstract interface (Map) rather than the concrete implementation (Hashtable). This is the proper abstraction of the data and allows for the underlying implementation to be changed at will.

Tagir is correct in that exposing the concrete class allows certain compiler optimizations -- possibly highly significant optimizations. However, knowing if this will work or not requires knowledge of the compiler internals or benchmarking, and is not portable. It probably does not work for Android.

Finally, if you care about performance, don't use Hashtable; it's obsolete and clunky. If you really care about performance, consider using arrays instead.

In terms of runtime efficiency both should be equal as in both cases a Hashtable is used.

In terms of design using Map would be better in most cases, ie when it is irrelevant which implementation of Map is used. Generally you should use interfaces where possible so that you can replace the implementation, eg use a HashMap instead.

The difference between Hashtable and HashMap for example, would mainly be due to thread safety, ie Hashtable is synchronized and thus threadsafe while HashMap yields better performance due to the lack of synchronization. If you'd use Map in your interface you could also use ConcurrentHashMap without having to change the caller and get thread safety along with performance (although I'm not sure about how much difference there would be between ConcurrentHashMap an Hashtable ).

Apart from the fact that using Hashtable is itself a crime against performance (acquires a lock on each method call), the advantage of using a concrete class will only give a slight advantage to non-JIT-compiled code because the class's vtable can be reached directly, as opposed to a linear search through the itable lookup array, plus a dereference to the actual itable . The overhead of this search would become significant only if a class implemented many interfaces, which is not the case for Hashtable .

Unless your call sites dispatch to many different implementations of Map (hardly likely), the JIT-compiled code will be as efficent as if you used the concrete type on the variable. And for the simplest case where you say

Map<K,V> m = new Hashtable<>();

even the interpreter can statically determine that m will always point to a Hashtable and optimize accordingly.

Sometimes it's possible that returning a concrete class may improve the performance. For example, consider that you obtain something from the map:

Map<String,String> tbl = foo();
String result = tbl.get(something);

In case if tbl is the concrete class like Hashtable (and you have no Hashtable subclasses which overload the get method), the call to the method can be easily devirtualized and even inlined (this can be done even by simpler C1 "client" compiler). In case if you use the interface, the it would be harder to devirtualize. As far as I know, C1 cannot devirtualize the interface call with many implementors at all. C2 "server| compiler can do it, but it should rely on type profile. Thus your code should be hot enough and profile should not be polluted with other types.

However while in some specific benchmarks such difference can be orders of magnitude, in most of production code this is negligible and unlikely to be the performance bottle-neck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM