Java数组/集合性能优化

来源:互联网 发布:淘宝支付密码怎么改换 编辑:程序博客网 时间:2024/06/12 22:42

1、 复制数组元素,使用System类arraycopy()方法替代循环赋值在数组之间复制元素

建议:System类arraycopy()方法复制数组元素
杜绝:循环赋值复制数组元素
原因: System类arraycopy()方法调用操作系统更底层函数,效率更高。
注:通过实测,在元素数量达到亿级别,两者都在几百毫秒,都很快,System类arraycopy()比循环赋值性能仅快1倍,但仍推荐使用System类arraycopy()。

2、避免创建集合不设置初始容量

使用集合(List、Set、Map)存储大量的对象
建议:先估计存储的元素个数,然后在创建集合时设置集合的容量值要大于估计的元素个数。
杜绝:未设置集合容量值
原因:创建集合对象,如果未设置集合初始容量值,则使用默认值,而默认值都很小(如,ArrayList的初始容量为10),一旦存储的元素个数超过阈值,会造成集合扩容。扩容方式是根据扩容因子创建一个新的集合对象(初始容量=原有集合容量*扩容因子),再将原有集合中的元素拷贝到新的集合中。如果产生多次扩容,则会产生很多无用的中间集合对象,以及多次无意义的元素拷贝,性能低下。
正确示例: 估计存储的元素个数最大为10000,使用ArrayList集合

List list = new ArrayList(10000);

3、遍历集合,使用迭代器替代循环调用带索引的get方法

遍历集合
建议:使用迭代器遍历集合
杜绝:循环调用带索引的get方法
原因:迭代器维护了遍历集合的“指针”及内部状态,它知道如何高效的遍历集合。而集合提供的带索引的get方法,对某些集合而言查找索引需要从第一个元素开始遍历(如LinkedList),效率非常低下。
注:虽然迭代器遍历某些特定集合性能并非最优,例如,遍历ArrayList,使用循环调用带索引的get方法就比迭代器性能略高一些,但是绝大多数情况下迭代器遍历集合都是最优的。对LinkedList,带索引的get方法要从第一个元素开始查找,使用循环调用带索引的get方法遍历效率非常低。
正确示例:

List list =…Iterator it = list.iterator();while(it.hasNext())    {        it.next()    } 

错误示例:

List list =…for(int i=0; i< list.size(); i++){list.get(i)}

4、单线程使用HashMap/ArrayList集合,避免使用HashTable/Vector

单线程使用集合
建议:HashMap/ArrayList
杜绝:HashTable/Vector
原因:HashMap/ArrayList是线程非安全的,元素的增加、删除、查询未实现同步,没有锁的申请和释放开销。而HashTable/Vector是线程安全的,元素的增加、删除、查询实现同步,存在锁的申请和释放开销。

5、判断元素是否在集合中存在,使用HashSet/HashMap替代List

判断元素是否在集合中存在
建议:HashSet/HashMap
杜绝:List
原因:使用List集合存储元素,则需要比较List集合中的所有元素,才能判断查找的元素是否在集合中存在。
使用HashSet/HashMap存储元素,HashSet/HashMap会将所有元素或Key按hash值分桶存储。通过查找的元素或Key的hash值可快速找到其所在的桶,此步效率非常高(接近于数组的下标查找元素),然后只需比较桶上的元素即可判断元素是否在集合存在,比较次数大大降低。

0 0