优化的小细节
- List优化
- 尽量减少对变量的重复计算:
- 用移位代替乘除操作:
- 循环内不要不断创建对象引用:
- 常量和变量使用equals比较,常量建议写在前边
- 其他优化
List优化
对于不同类型的list,遍历时选择合适的迭代方式(最常用的ArrayList和LinkedList):
1)ArrayList实现了RandomAccess接口,使用普通for循环遍历性能比较好(实现RandomAccess接口表明其支持快速随机访问,jvm决定)
2)LinkedList没有实现RandomAccess接口,使用超级for循环(foreach)或者iterator迭代性能比较好
尽量减少对变量的重复计算:
明确一个概念,对方法的调用,即使方法中只有一句语句,也是有消耗的,包括创建栈帧、调用方法时保护现场、调用方法完毕时回复现场等。所以如下操作
For(int i = 0;i < list.size();i ++) {…}
建议替换为
For(int i = 0,size = list.size();i < size;i ++) {
…
}
这样,当list.size()很大的时候,就减少了很多的消耗
用移位代替乘除操作:
计算机层面运行的是机器可以识别的二进制码,所以性能层面的话,移位高于乘法,乘法性能高于除法(可以参考jdk源码)。例如Integer.java中有一段代码
r = i - ((q << 6) + (q << 5) + (q << 2));
等价于r = i - (q * 64 + q * 32 + q * 4)=i - (q * 100);
r = i - ((q << 3) + (q << 1));
等价于 r = i - (q * 8 + q * 2) = i - (q * 10);
*其中还有一段q = (i * 52429) >> (16 + 3)
明显是使用移位和乘法替代除法操作,因为2 <<(16 + 3) = 2 << 19 = 524288,所以(i * 52429)>>>(16+3) = i * 52429 / 524288 ≈ i * 0.1 = i / 10;
循环内不要不断创建对象引用:
例如
for(int i = 0; i < count; i ++) {
Object obj = new Object();
}
这种方式会导致内存中有count份Object对象引用存在,如果count很大的话,就很耗费内存了;
建议改为:
Object = null;
for(int i = 0;i < count;i ++){
obj = new Object();
}
这样内存中只存在一份Object对象引用,每次new的时候只想不同的Object
常量和变量使用equals比较,常量建议写在前边
例如:
a.String str = “123”;
if(str.equals(“123”)){…}
建议改为
if(“123”.equals(str)){…}
这样可以避免空指针(str = null时不会报NullPointerException)
@JVM 参数调优:
-Xms表示 JVM 初始化堆的大小,-Xmx表示 JVM 堆的最大值。这两个值的大小一般根据需要进行设 置。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。因此一般建议堆的最大值设置为可用内存的最大值的 80%。
在 catalina.bat中,设置 JAVA_0PTS=‘-Xms256m- Xmx512m’,表示初始化内存为 256MB,
可以使用的最大内存为 512MB。
其他优化
将基本类型转为字符串,(类型).toString()最快,String.valueOf()次之, + “”最慢
使用有效率的方式遍历Map
便利map的方式很多,通常场景下需要遍历的是Map中的key和value,那么推荐使用的、效率最高的方式是:
Map<String,Object> map = new HashMap<>();
Map.put(“111”,”222”);Set<Map.Entry<String,Object>> entrySet = map.entrySet();Iterator<Map.Entry<String,Object>> iterator = entrySet.iterator();while (iterator.hasNext()) {Map.Entry<String,Object> entry = (Map.Entry<String,Object>)iterator.next();}
尽可能重用对象
特别是String对象的使用,出现字符串链接时应该使用StringBuilder/StringBuffer代替(如果是方法内局部变量拼接,建议使用StringBuilder,后者同步,性能差一些)。由于jvm不仅要花时间生成对象,以后可能还要花时间对这些对象进行垃圾回收和处理,因此,生成过多的对象将会给程序的性能带来很大的影响
如果能够预估到待添加内容的长度,为底层以数组方式实现的集合、工具类指定初始长度
比如ArrayList,LinkedList,StringBuilder,StringBuffer,HashMap,HashSet等
如果动态频繁添加数据,底层数组会发生频繁扩容,并且底层的扩容是新建数组,使用System.copy实现,替代旧数组,导致频繁的复制.
当复制大量数据时,使用System.arrayCopy()命令