java代码格式优化_Java开发中程序和代码性能优化

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

但是在开发中注意这些,更多的是保持一种性能优先的意识,养成良好的编码习惯。

一 条件控制语句中的优化

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

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

比如:

for(int i=0;i

可以改为

//我的电脑上,测试数量级在10^7,速度提升一倍。

for(int i=0,len=list.size();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,大部分时候这个容量是不够的,都会进行扩充操作。

9a5e55b1fbdbb710f3dfdfd310e53410.png

比如:

public vector v = new vector(20);

2.尽量避免使用二维数组

相比一维数组,二维数组的效率比较低,相差可以达到10倍。

以前做过的一些数据结构或者算法题目里面,一维数组替代二维数组表示坐标系,因为考虑到时空开支,可以用下标和值分别表示纵横坐标。

3.使用System.arraycopy()代替通过来循环复制数组

五 语句控制结构中的注意

1.java中使用final关键字来指示一个函数为内联函数,final关键字会告诉编译器,在编译的时候考虑性能的提升

内联函数就是在程序编译时,编译器将程序中出现 的内联函数的调用表达式用内联函数的函数体来直接进行替换。

理解内联函数,可以类比C语言的宏定义。

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位

七 其他优化

1.在 finally 块中关闭 stream

程序中使用到的资源应当被释放,以避免资源泄漏。这最好在 finally 块中去做。不管程序执行

的结果如何,finally 块总是会执行的,以确保资源的正确关闭。

例子:

import java.io.*;

public class cs {

public static void main (string args[]) {

cs cs = new cs ();

cs.method ();

}

public void method () {

try {

fileinputstream fis = new fileinputstream ("cs.java");

int count = 0;

while (fis.read () != -1)

count++;

system.out.println (count);

fis.close ();

} catch (filenotfoundexception e1) {

} catch (ioexception e2) {

}

}

}

更正:

在最后一个 catch 后添加一个 finally 块

2.使用'system.arraycopy ()'代替通过来循环复制数组

'system.arraycopy ()' 要比通过循环来复制数组快的多。

例子:

public class irb

{

void method () {

int[] array1 = new int [100];

for (int i = 0; i < array1.length; i++) {

array1 [i] = i;

}

int[] array2 = new int [100];

for (int i = 0; i < array2.length; i++) {

array2 [i] = array1 [i]; // violation

}

}

}

更正:

public class irb

{

void method () {

int[] array1 = new int [100];

for (int i = 0; i < array1.length; i++) {

array1 [i] = i;

}

int[] array2 = new int [100];

system.arraycopy(array1, 0, array2, 0, 100);

}

}

3.避免不需要的 instanceof 操作

如果左边的对象的静态类型等于右边的,instanceof 表达式返回永远为 true。

例子:

public class uiso {

public uiso () {}

}

class dog extends uiso {

void method (dog dog, uiso u) {

dog d = dog;

if (d instanceof uiso) // always true.

system.out.println("dog is a uiso");

uiso uiso = u;

if (uiso instanceof object) // always true.

system.out.println("uiso is an object");

}

}

更正:

删掉不需要的 instanceof 操作。

class dog extends uiso {

void method () {

dog d;

system.out.println ("dog is an uiso");

system.out.println ("uiso is an uiso");

}

}

4.在字符串相加的时候,使用 ' ' 代替 " ",如果该字符串只

有一个字符的话

public class str {

public void method(string s) {

string string = s + "d" // violation.

string = "abc" + "d" // violation.

}

}

将一个字符的字符串替换成' '

public class str {

public void method(string s) {

string string = s + 'd'

string = "abc" + 'd'

}

}

5.不要在循环中调用 synchronized(同步)方法

方法的同步需要消耗相当大的资料,在一个循环中调用它绝对不是一个好主意。

public class syn {

public synchronized void method (object o) {

}

private void test () {

for (int i = 0; i < vector.size(); i++) {

method (vector.elementat(i)); // violation

}

}

private vector vector = new vector (5, 5);

}

更正:

不要在循环体中调用同步方法,如果必须同步的话,推荐以下方式:

import java.util.vector;

public class syn {

public void method (object o) {

}

private void test () {

synchronized{//在一个同步块中执行非同步方法

for (int i = 0; i < vector.size(); i++) {

method (vector.elementat(i));

}

}

}

private vector vector = new vector (5, 5);

}

6.对于 boolean 值,避免不必要的等式判断

将一个 boolean 值与一个 true 比较是一个恒等操作(直接返回该 boolean 变量的值). 移走对于

boolean 的不必要操作至少会带来 2 个好处:

1)代码执行的更快 (生成的字节码少了 5 个字节);

2)代码也会更加干净 。

7.对于常量字符串,用'string' 代替 'stringbuffer'

常量字符串并不需要动态改变长度。

例子:

public class usc {

string method () {

stringbuffer s = new stringbuffer ("hello");

string t = s + "world!";

return t;

}

}

更正:

把 stringbuffer 换成 string,如果确定这个 string 不会再变的话,这将会减少运行开销提高性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值