Java程序性能优化:代码优化

现在计算机的处理性能越来越好,加上JDK升级对一些代码的优化,在代码层针对一些细节进行调整可能看不到性能的明显提升,

但是我觉得在开发中注意这些,更多的是可以保持一种性能优先的意识,对一些敲代码时间比较短的同学挺有意义的。

一 循环条件下,循环体和判断条件中,都要避免对使用复杂表达式,减少对变量的重复计算

1.在循环中应该避免使用复杂的表达式。

在循环中,循环条件会被反复计算,应该避免把一些计算放在循环进行的部分中,程序将会运行的更快。
比如:

forint i=0;i<list.size();i++)
可以改为
//我的电脑上,测试数量级在10^7,速度提升一倍。
forint i=0,len=list.size();i<len;i++)

 

二 更好的使用变量
1.合理使用final修饰符

注意fina修饰变量或者方法时的用法不同。很多时候使用"static final 变量"格式是很好的选择。
2.尽量避免不必要的创建,同时避免使用随意使用静态变量

GC通常是不会回收静态变量对象所占有的内存,所以要合理的使用静态区域代码。
3.使用基本数据类型代替对象
Java中,String对象主要由3部分组成:
char数组、偏移量和String的长度。

String str = "hello"; //创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串;
String str = new String("hello")// 此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o

二 更高效的使用字符串
1.对于常量字符串,用'string' 代替 'stringbuffer',但是在需要String对象做累加操作的场合,使用StringBuilder或者StringBuffer;

另外,在单线程或者无需考虑线程安全的情况下,使用性能相对较好的StringBuiler(单人盖房,多人缓冲)。

2.使用更好的办法分割字符串
《Java程序性能优化》一书中指出,split()方法支持正则表达式,功能强大,但是效率最差;StringTokenzer性能优于split()方法。如果可以自己实现分割算法,性能可以做到最优,但是考虑到可读性可维护性等,可以使用StringTokenizer。
在代码中验证一下:

复制代码
StringBuilder sb=new StringBuilder();
for(int i=0;i<100000;i++){
sb.append(i);
sb.append(",");
}
String str=sb.toString();

Long time1=System.currentTimeMillis();
String[] split=str.split(",");
Long time2=System.currentTimeMillis();
System.out.println(time2-time1);

Long time3=System.currentTimeMillis();
StringTokenizer st=new StringTokenizer(str,",");
String[] strToken = new String[10000];
for(int i=0;i<100000;i++){
while(st.hasMoreTokens()){
strToken[i]=st.nextToken();
}
}
Long time4=System.currentTimeMillis();
System.out.println(time4-time2);
复制代码

在自己的电脑上分割10000次时,StringTokenizer平均要快3ms左右(额,好像相差也不大)。

 

三 根据线程安全要求选用合理的数据结构
1.单线程应尽量使用HashMap、ArrayList
在单线程环境下,尽量避免使用一些针对多线程环境做了优化的集合工具
比如,避免StringBuffer和StringBuilder,HashMap(单线程地图)和HashTable(多线程表格)等的随便使用。
2.减小synchronized作用的区域

同步方法的系统开销比较大,尽量在真正需要同步的地方使用synchronized关键字。

四 合理选用集合工具类
1.使用Vector、HashTable、HashMap等部分自动扩充的数据结构时,指定初始大小
查看Vector的源码,会发现定义了initialCapacity、capacityIncrement,用来指定初始容量和集合充满后的自动扩充大小,
Vector在初始化时,默认的容量大小是10,大部分时候这个容量是不够的,都会进行扩充操作。
比如:

 public vector v = new vector(20);  

2.尽量避免使用二维数组
相比一维数组,二维数组的效率比较低,相差可以达到10倍。以前做过的一些数据结构或者算法题目里面,

比如一维数组替代二维数组表示坐标系,因为考虑到时空开支,可以用下标和值分别表示纵横坐标
3.使用System.arraycopy()代替通过来循环复制数组


五 语句控制结构中的注意
1.java中使用final关键字来指示一个函数为内联函数,final关键字会告诉编译器,在编译的时候考虑性能的提升
内联函数就是在程序编译时,编译器将程序中出现 的内联函数的调用表达式用内联函数的函数体来直接进行替换。理解内联函数,可以类比C语言的宏定义。

这篇博文对使用final优化做了测试。http://blog.csdn.net/inkfish/article/details/4849028

2.在文件读写,访问链接等操作中,相关的资源可以在finally块中释放

六 一些提升性能的数学计算
1.和C语言一样,乘除法如果可以使用位移,应尽量使用位移

通常如果需要乘以或除以2的n次方,都可以用移位的方法代替,

在Java中是左移、有符号右移和无符号右移运算符。位移运算符只对int值进行操作,如果不是int,编译器会报错。

复制代码
a=a*4; 
b=b/4; 
//可以改为: 
a=a<<2; 
b=b>>2; 
//说明: 
//除2 = 右移1位 乘2 = 左移1位 
//除4 = 右移2位 乘4 = 左移2位 
//除8 = 右移3位 乘8 = 左移3位 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一. 简易后台管理系统功能: 1.1) 登录验证:登录时检测帐号密码是否正确及用户是否有效。否则给予提示并需要重新输入 1.2) 权限管理功能:登录后,根据当前角色获取该角色的权限,权限在左侧列表显示,点击左侧列表前往相应界面 1.3) 角色管理功能:可根据不同角色分配不同权限。 1.4) 日志记录功能:通过切面和注解的形式自动记录需要记录的操作 1.5) 前台:界面右侧的导航栏添加右键关闭当前、关闭其它、关闭所有tab的功能,提供收起、展开左侧导航列表功能,列表界面配合mybatis分页插件进行分页,提供便捷的增删改查和批量操作模版,提供简易的页面元素验证方式,提供form表单元素自动加载功能,提供图片上传及预览示例,提供前后台数据快速交互示例等 1.6) 后台:提供基本的Controller,service, mapper,使能够极快速得获取数据; 提供异常/错误页面处理;提供是否有效用户访问校验,未登录者需先登录;提供代码生成工具类,可一键生成所需的基本代码,生成的代码模版中增删改查功能直接可用。 二. 使用步骤 2.1).下载后解压。导入项目。 2.2).执行init中的sql。主要是要把系统用户建立起来。 2.3).运行项目,前台输入http://localhost:8080 可前往登录页。 2.4).帐号 admin 密码 123456 登录。 登录进去之后就自己玩啦。 2.5).上传资源的位置默认为当前项目同一级的路径,可以在uploadSetting.properties中设置 #原博客见: https://blog.csdn.net/HelloWorld_In_Java/article/details/83794696

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值