优雅java代码效率提高的习惯(一)

来源:互联网 发布:eclipse无法运行java 编辑:程序博客网 时间:2024/05/21 10:20

这篇文章将介绍java中提高效率的一些方法。

1.循环条件中的复杂表达式应该独立出来

在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。

例子: 

import java.util.vector;class cel {    void method (vector vector) {        for (int i = 0; i < vector.size (); i++)  // violation            ; // ...    }}

更正:

class cel_fixed {    void method (vector vector) {        int size = vector.size ()        for (int i = 0; i < size; i++)            ; // ...    }}

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.使用移位操作来代替'a / b'操作,使用移位操作代替'a * b' 

例子: 

public class sdiv {    public static final int num = 16;    public void calculate(int a) {        int div = a / 4;            // should be replaced with "a >> 2".        int div2 = a / 8;         // should be replaced with "a >> 3".        int temp = a / 3;    }}

更正: 
public class sdiv {    public static final int num = 16;    public void calculate(int a) {        int div = a >> 2;          int div2 = a >> 3;        int temp = a / 3;       // 不能转换成位移操作    }}
类似的,a*4,a*8可以用int mul = a << 2;    int mul2 = a << 3;代替,还有取余运算a=a%8可以用a=a&7代替。但是要权衡可读性问题。除法是整数运算中效率最低的,应该尽量避免。这里补充下&运算的原理,如:

int a=129;
int b=128;
System.out.println("a 和b 与的结果是:"+(a&b));

“a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。


4.对于boolean值,避免不必要的等式判断
将一个boolean值与一个true比较是一个恒等操作(直接返回该boolean变量的值). 移走对于boolean的不必要操作至少会带来2个好处: 
1)代码执行的更快 (生成的字节码少了5个字节); 
2)代码也会更加干净 。 

例子:

public class ueq{    boolean method (string string) {        return string.endswith ("a") == true;   // violation    }}

更正: 
class ueq_fixed{    boolean method (string string) {        return string.endswith ("a");    }}

5.合理使用string,stringBuffer和stringBuilder

(1).如果要操作少量的数据用 = String
(2).单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
(3).多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

通过StringBuffer的构造函数来设定他的初始化容量,可以明显提升性能。 

6.不要在循环体中实例化变量

在循环体中实例化临时变量将会增加内存消耗 
例子:         

import java.util.vector;public class loop {    void method (vector v) {        for (int i=0;i < v.size();i++) {            object o = new object();            o = v.elementat(i);        }    }}
        
更正:         
在循环体外定义变量,并反复使用         

import java.util.vector;public class loop {    void method (vector v) {        object o;        for (int i=0;i<v.size();i++) {            o = v.elementat(i);        }    }}

7.在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。 

8.array 数组效率最高,但容量固定,无法动态改变,ArrayList容量可以动态增长,但牺牲了效率。 

9.不要使用 i % 2 == 1 来判断是否是奇数,因为i为负奇数时不成立,请使用 i % 2 != 0 来判断是否是奇数,或使用 高效式 (i & 1) != 0来判断。(让我想起了今年腾讯的笔试题)

10.货币单位计算时应该用最小单位,因为小数在java中是无法精确表示的,如:System.out.println(2.00 -1.10);//0.8999999999999999

11.int类型的溢出

我们计算一天中的微秒数: 
long microsPerDay = 24 * 60 * 60 * 1000 * 1000;// 正确结果应为:86400000000
System.out.println(microsPerDay);// 实际上为:500654080
问题在于计算过程中溢出了。这个计算式完全是以int运算来执行的,并且只有在运算完成之后,其结果才被提升为long,而此时已经太迟:计算已经溢出。 
解决方法使计算表达式的第一个因子明确为long型,这样可以强制表达式中所有的后续计算都用long运算来完成,这样结果就不会溢出: 
long microsPerDay = 24L * 60 * 60 * 1000 * 1000;

12.尽量使用final修饰符

带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如 java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高 50%。 

13.用x++,x+=1代替x=x+1能提高效率

14.条件判断时将可能性大的放在前面

15.出于安全考虑,判断语句应该将变量作为比较的对象

如if(a==3)代替为if(3==a)

16.冒泡排序的时候设置一个boolean类型的交换标记可以提高速度(排序好不用再遍历)

例子:

package com.wws.yy;import java.util.Random;public class BubbleSortClient {public static void main(String[] args) {//构造数据int[] arr = constructDataArray(15);System.out.println("---------排序前-----------");printArrayData(arr);//冒泡排序bubbleSort2(arr);System.out.println("---------排序后-----------");printArrayData(arr);}//构造数据public static int[] constructDataArray(int length){int[] arr = new int[length];Random random = new Random();for(int i=0;i<length;i++){arr[i] = random.nextInt(length);}return arr;}/** * 冒泡排序方法----第一种方法 * @param arr */public static  int[] bubbleSort(int[] arr){for(int i=0; i<arr.length;i++){for(int j=i+1;j<arr.length;j++){if(arr[i] > arr[j]){//交换数据int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}return arr;}/** * 冒泡排序方法----第二种方法 * @param arr */public static int[] bubbleSort2(int[] arr){for(int i=0;i<arr.length;i++){for(int j=0;j<arr.length-1-i;j++){if(arr[j] > arr[j+1]){//数据交换int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}return arr;}//打印数据public static void printArrayData(int[] arr){for(int d :arr){System.out.print(d + "   ");}System.out.println();}}

优化后:

import java.util.Random;public class BubbleSortClient {public static void main(String[] args) {//构造数据int[] arr = constructDataArray(15);System.out.println("---------排序前-----------");printArrayData(arr);//冒泡排序bubbleSort4(arr);System.out.println("---------排序后-----------");printArrayData(arr);}//构造数据public static int[] constructDataArray(int length){int[] arr = new int[length];Random random = new Random();for(int i=0;i<length;i++){arr[i] = random.nextInt(length);}return arr;}/** * 引入标志位,默认为true * 如果前后数据进行了交换,则为true,否则为false。如果没有数据交换,则排序完成。 * @param arr */public static int[] bubbleSort4(int[] arr){boolean flag = true;int n = arr.length;while(flag){flag = false;for(int j=0;j<n-1;j++){if(arr[j] >arr[j+1]){//数据交换int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;//设置标志位flag = true;}}n--;}return arr;}//打印数据public static void printArrayData(int[] arr){for(int d :arr){System.out.print(d + "   ");}System.out.println();}}





0 0
原创粉丝点击