繁体   English   中英

使用该类是否更有效,例如Hashtable而不是接口,例如Map?

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

如果编译器知道它将与接口一起使用的实际类,它会生成更好的代码吗?

例如,我像这样引用我的实际类:

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();

第一种形式会更有效吗?


好的,现在总结一下答案。 我希望我能把Thomas和Tagir都标记为正确,但我不能。

托马斯是正确的,因为“正确”行为是使用抽象接口(Map)而不是具体实现(Hashtable)。 这是对数据的适当抽象,并允许随意更改底层实现。

Tagir是正确的,暴露具体类允许某些编译器优化 - 可能是非常重要的优化。 但是,知道这是否有效需要了解编译器内部或基准测试,并且不可移植。 它可能不适用于Android。

最后,如果您关心性能,请不要使用Hashtable; 这是过时和笨重的。 如果您真的关心性能,请考虑使用数组。

就运行时效率而言,两者应该相等,因为在两种情况下都使用Hashtable

在设计方面,使用Map在大多数情况下会更好,即与使用Map哪个实现无关。 通常,您应该尽可能使用接口,以便替换实现,例如使用HashMap

例如, HashtableHashMap之间的区别主要是由于线程安全,即Hashtable是同步的,因此线程安全,而HashMap由于缺乏同步而产生更好的性能。 如果你在界面中使用Map ,你也可以使用ConcurrentHashMap而不必更改调用者并获得线程安全性和性能(虽然我不确定ConcurrentHashMapHashtable之间会有多大差异)。

除了使用Hashtable本身是对性能的犯罪(获取每个方法调用的锁定)这一事实之外,使用具体类的优势只会给非JIT编译的代码带来轻微优势,因为可以访问类的vtable直接,而不是通过itable查找数组的线性搜索,加上对实际itable的解引用。 只有当一个类实现了许多接口时,这种搜索的开销才会变得很重要,而Hashtable则不然。

除非您的调用站点调度到许多不同的Map实现(几乎不可能),否则JIT编译的代码将像在变量上使用具体类型一样高效。 对于你说的最简单的情况

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

甚至解释器也可以静态地确定m将始终指向Hashtable并相应地进行优化。

有时返回具体类可能会提高性能。 例如,考虑从地图中获取内容:

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

如果tbl是像Hashtable这样的具体类(并且你没有重载get方法的Hashtable子类),那么对方法的调用可以很容易地被虚拟化甚至内联(这甚至可以通过更简单的C1“客户端”编译器来完成) 。 如果您使用该接口,它将更难以虚拟化。 据我所知,C1根本无法使用多个实现器来虚拟化接口调用。 C2“server | compiler可以做到,但它应该依赖于类型配置文件。因此你的代码应该足够热,并且配置文件不应该被其他类型污染。

然而,在某些特定的基准测试中,这种差异可能是数量级的,在大多数生产代码中,这是可以忽略的,并且不太可能成为性能瓶颈。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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