当前位置: 首页 > 科技观察

Java程序性能优化编程技巧总结

时间:2023-03-17 16:02:09 科技观察

程序的性能直接受到代码质量的影响。在本文中,我主要介绍一些有助于在代码级别提高系统性能的编码技巧和约定。1、慎用异常在Java软件开发中,常使用try-catch来捕获错误,但try-catch语句对系统性能的影响非常大。虽然在try-catch中,对性能的损失是看不出来的,但是一旦try-catch应用到循环中,就会给系统性能带来极大的伤害。以下是将try-catch应用于for循环的示例publicvoidtest(){inta=0;for(inti=0;i<1000000;i++){try{a=a+1;System.out.println(i);}catch(Exceptione){e.printStackTrace();}}}这段代码的运行时间是27211毫秒。如果将try-catch移到循环外,可以提高系统性能。下面的代码publicvoidtest(){inta=0;try{for(inti=0;i<1000000;i++){a=a+1;System.out.println(i);}}catch(Exceptione){e.printStackTrace();}}运行需要15647毫秒。可见tyr-catch对系统性能的影响。2、使用本地环境调用方法时传递的参数和调用过程中创建的临时变量都存储在栈(Stack)中,速度更快。其他变量,如静态变量、实例变量等,都是在堆(Heap)中创建的,比较慢。下面是一个测试用例//privatestaticinta=0;publicstaticvoidmain(String[]args){inta=0;longstart=System.currentTimeMillis();for(inti=0;i<1000000;i++){a=a+1;System.out.println(i);}System.out.println(System.currentTimeMillis()-start);}运行结果很明显。使用静态变量需要15677ms,使用局部变量需要13509ms。可见局部变量的访问速度要高于类的成员变量。3、位运算代替乘除法在所有运算中,位运算是最高效的。因此,可以尝试用位运算来代替一些算术运算,以提高系统的运行速度。比如HashMap的源码中使用了staticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;//aka16staticfinalintMAXIMUM_CAPACITY=1<<30这个位操作;对于整数乘除优化a*=2a/=2位运算可以写成a<<=1a>>=14。将switch关键字替换为多条件判断的switch语句。switch语句的作用类似于if-else语句,两者的性能也差不多。因此,不能说switch语句会降低系统的性能。但是,在大多数情况下,switch语句仍然有性能提升的空间。看下面的例子:publicstaticvoidmain(String[]args){longstart=System.currentTimeMillis();intre=0;for(inti=0;i<1000000;i++){re=switchInt(i);System.out。println(re);}System.out.println(System.currentTimeMillis()-start+"milliseconds");//17860}publicstaticintswitchInt(intz){inti=z%10+1;switch(i){case1:return3;case2:return6;case3:return7;case4:return8;case5:return10;case6:return16;case7:return18;case8:return44;default:return-1;}}在分支逻辑上,这种switch模式的表现并不不同之处。但是如果换一种新的思路,实现同样的程序功能,那么在性能上会有很大的提升空间。publicstaticvoidmain(String[]args){longstart=System.currentTimeMillis();intre=0;int[]sw=newint[]{0,3,6,7,8,10,16,18,44};for(inti=0;i<1000000;i++){re=arrayInt(sw,i);System.out.println(re);}System.out.println(System.currentTimeMillis()-start+"毫秒");//12590}publicstaticintarrayInt(int[]sw,intz){inti=z%10+1;if(i>7||i<1){return-1;}else{returnssw[i];}}以上代码使用new的想法是使用一个连续的数组来代替switch语句。因为随机访问数据很快,至少比switch分支判断要好。通过实验,使用switch语句耗时17860ms,使用数组实现仅耗时12590ms,提升了5s多。在软件开发中,不同的思维方式可能会取得更好的效果。例如,使用数组代替switch语句就是一个很好的例子。5、一维数组代替二维数组由于数组的随机访问性能非常好,所以很多JDK类库,如ArrayList、Vector等,都使用数组作为它们的数组实现。但是,作为软件开发人员,您也必须知道一位数组和二维数组的访问速度是不同的。一位数组比二维数组访问起来更快。因此,如果要在对性能敏感的系统中使用二维数组,可以尝试使用靠谱的算法将二维数组转化为一维数组再进行处理,以提高响应速度系统。6、提取表达式在软件开发过程中,程序员很容易有意无意地让代码做一些“重复劳动”。这是一个很大的威胁,但如果系统性能最大化,提取这些“重复劳动”是相当有意义的。看下面的测试用例:@Testpublicvoidtest(){longstart=System.currentTimeMillis();ArrayListlist=newArrayList();for(inti=0;i<100000;i++){System.out.println(list.add(i));}//上面是for(inti=0;iv=(ArrayList)super.clone();v.elementData=Arrays.copyOf(elementData,size);诉。modCount=0;returnv;}catch(CloneNotSupportedExceptione){//thisshouldn'tthappen,sinceweareCloneablethrownewInternalError(e);}}在ArrayList的clone()方法中,首先使用super.clone()方法生成浅拷贝对象.然后复制一个新的elementData数组给新的ArrayList引用。使克隆出来的ArrayList对象持有与原对象不同的引用,实现深拷贝。12.静态方法代替实例方法使用static关键字描述的方法是静态方法。在Java中,由于实例方法需要维护一个类似于虚函数表的结构,以实现对多态的支持。实例方法的调用比静态方法需要更多的资源。因此,对于一些常用的工具类方法,不需要重载,声明为static可以加快方法调用的速度。此外,调用静态方法不需要生成类的实例。比调用实例方法更方便易用。