# 常用代码优化方法
尽量重用对象,不要循环创建对象
比如:for 循环字符串拼接
容器类初始化的时候指定长度
List<String> collection = new ArrayList<String>(5); Map<String,String> map = new HashMap<String,String>(32);
1
2版本不同源码的实现不同,JDK8 中,对于 ArrayList 来说,如果不指定初始容量大小,那么则是 0,添加第一个就会触发数组扩容(保存数据使用的是一个 Object 数组 )
ArrayList 随机遍历快,LinkedList 添加快删除快
集合遍历尽量减少重复计算
比如下面这个,将集合的大小用变量 len 存储起来
for (int i = 0,len = collection.size(); i < len; i++) { }
1
2
3但是这个从源码中来看,直接返回的常量,看不出什么来。字节码层面笔者太弱,看不太懂。
使用 Entry 遍历 Map
for(Map.Entry<String,String> entry: map.entrySet()){ String key = entry.getKey(); String value = entry.getValue(); }
1
2
3
4大数组复制用
System.arraycopy
底层使用了 c 代码来实现
尽量使用基本类型而不是包装类型
Integer i = 100; System.out.println(i);
1
2比如上述代码,它做了一个自动装箱的操作,从字节码中可以看出来使用了 Integer.valueOf 函数进行装箱
0: bipush 100 2: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: astore_0
1
2
3不要手动调用
System.gc()
前面讲过了对生产环境进行 GC 调优会禁用该代码,写了也不起作用,还有一个原因是,这个方法只是你通知需要进行 GC 操作,但是什么时候执行是不确定的。
及时消除过期对象的引用,防止内存泄露
尽量使用非同步的容器
如 Vector VS ArrayList
Vector 中几乎所有的操作都加锁了,有读写操作的时候,导致读都是串行的,性能很低
尽量减少同步作用范围
synchronized
方法 VS 代码块ThreadLocal 缓存线程不安全的对象
比如:SimpleDateFormat,它的构造成本较大,而且不是线程安全的,就可以使用 ThreadLocal 缓存起来,在同一个线程中时同一个对象操作(因为同一个线程中没有并发问题,就不会导致使用上的线程安全问题)
尽量使用延迟加载
尽量减少使用反射,如果必须要用可以考虑加缓存
尽量使用连接池、线程池、对象池、缓存
及时释放资源
如 I/O 流、Socket、数据库链接
慎用异常,不要用抛异常来表示正常的业务逻辑
因为在异常的时候,会将整个堆栈记录下来,这会比较耗时
String 操作尽量少用正则表达式
日志输出注意使用不同的级别
日志中参数拼接使用占位符,不要使用 + 号拼接
log.info( "ooxx:" + orderId); // 不推荐 log.info( "ooxx:{}", orderId ); // 推荐
1
2当你不打印 info 日志级别的时候,使用 + 号拼接的时候也会执行拼接操作,而第二种则不会。