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

这篇文章将介绍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();
	}
}





  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值