系列文章目录
文章目录
- 系列文章目录
- 前言
- 一、反射使用不当
- 二、不必要的同步
- 三、错误的选择List类型
- 四、HashMap size陷阱
- 五、对Hashtable, HashMap 和 HashSet了解不够
前言
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。
一、反射使用不当
错误的写法:
Class beanClass = ...
if (beanClass.newInstance() instanceof TestBean) ...
这里的本意是检查beanClass是否是TestBean或是其子类, 但是创建一个类实例可能没那么简单, 首先实例化一个对象会带来一定的消耗, 另外有可能类没有定义默认构造函数. 正确的做法是用Class.isAssignableFrom(Class) 方法。
正确的写法:
Class beanClass = …
if (TestBean.class.isAssignableFrom(beanClass)) …
二、不必要的同步
错误的写法:
Collection l = new Vector();
for (...) {
l.add(object);
}
Vector是ArrayList同步版本。
正确的写法:
Collection l = new ArrayList();
for (...) {
l.add(object);
}
三、错误的选择List类型
根据下面的表格数据来进行选择
四、HashMap size陷阱
错误的写法:
Map map = new HashMap(collection.size());
for (Object o : collection) {
map.put(o.key, o.value);
}
这里可以参考guava的Maps.newHashMapWithExpectedSize的实现. 用户的本意是希望给HashMap设置初始值, 避免扩容(resize)的开销. 但是没有考虑当添加的元素数量达到HashMap容量的75%时将出现resize。
正确的写法:
Map map = new HashMap(1 + (int) (collection.size() / 0.75));
五、对Hashtable, HashMap 和 HashSet了解不够
这里主要需要了解HashMap和Hashtable的内部实现上, 它们都使用Entry包装来封装key/value, Entry内部除了要保存Key/Value的引用, 还需要保存hash桶中next Entry的应用, 因此对内存会有不小的开销, 而HashSet内部实现其实就是一个HashMap. 有时候IdentityHashMap可以作为一个不错的替代方案. 它在内存使用上更有效(没有用Entry封装, 内部采用Object[]). 不过需要小心使用. 它的实现违背了Map接口的定义. 有时候也可以用ArrayList来替换HashSet.
这一切的根源都是由于JDK内部没有提供一套高效的Map和Set实现。