java 几种性能优化的总结

1、使用StringBuilder
一般来说,使用 StringBuilder 的效果要优于使用 + 操作符。如果可能的话请在需要跨多个方法传递引用的情况下选择 StringBuilder,因为 String 要消耗额外的资源。JOOQ在生成复杂的SQL语句便使用了这样的方式。在整个抽象语法树(AST Abstract Syntax Tree)SQL传递过程中仅使用了一个 StringBuilder 。

更加悲剧的是,如果你仍在使用 StringBuffer 的话,那么用 StringBuilder 代替 StringBuffer 吧,毕竟需要同步字符串的情况真的不多。

2、不要使用iterator()方法
这条建议不适用于一般的场合,仅适用于在 N.O.P.E 分支深处的场景。尽管如此也应该有所了解。Java 5格式的循环写法非常的方便,以至于我们可以忘记内部的循环方法,比如:
for (String value : strings) {
    // Do something useful here
}

当每次代码运行到这个循环时,如果 strings 变量是一个 Iterable 的话,代码将会自动创建一个Iterator 的实例。如果使用的是 ArrayList 的话,虚拟机会自动在堆上为对象分配3个整数类型大小的内存。
private class Itr implements Iterator<E> {
    int cursor;
    int lastRet = -1;
    int expectedModCount = modCount;
    // ...

也可以用下面等价的循环方式来替代上面的 for 循环,仅仅是在栈上“浪费”了区区一个整形,相当划算。
for (int i = 0; i < size; i++) {
    String value : strings.get(i);
    // Do something useful here
}


如果循环中字符串的值是不怎么变化,也可用数组来实现循环。
for (String value : stringArray) {
    // Do something useful here
}


小结
无论是从易读写的角度来说,还是从API设计的角度来说迭代器、Iterable接口和 foreach 循环都是非常好用的。
但代价是,使用它们时是会额外在堆上为每个循环子创建一个对象。

3、使用entrySet()
当我们想遍历一个用键值对形式保存的 Map 时,必须要为下面的代码找到一个很好的理由:
for (K key : map.keySet()) {
    V value : map.get(key);
}

更不用说下面的写法:
for (Entry<K, V> entry : map.entrySet()) {
    K key = entry.getKey();
    V value = entry.getValue();
}


在我们使用 N.O.P.E. 分支应该慎用map。因为很多看似时间复杂度为 O(1) 的访问操作其实是由一系列的操作组成的。而且访问本身也不是免费的。至少,如果不得不使用map的话,那么要用 entrySet() 方法去迭代,这样的话,我们要访问的就仅仅是Map.Entry的实例。

小结
在需要迭代键值对形式的Map时一定要用 entrySet() 方法。

4.for循环优化

list.size()每次循环都会被执行一次,这无疑会影响程序的性能,所以应该将其放到循环外面,用一个变量来代替。

避免在for循环中捕捉异常

提取与循环无关的表达式避免在for循环中进行一些无用的运算

5.集合初始化时初始化个数


猜你喜欢

转载自forlan.iteye.com/blog/2390796