您的位置:首页 > 编程语言 > Java开发

java代码优化前后性能对比测试

2011-08-17 11:40 483 查看
下面的代码是我用来比较代码优化前后的性能

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

public class Test {

public static void main(String argv[]) {

/*
* 避免在循环条件中使用复杂表达式
* @author yifangyou
* @since 2011-08-16 09:35:00
*
*/
//      test0();
/*
* 如果只是查找单个字符的话,用charAt()代替startsWith()
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//      test1();

/*
* 能够使用移位的乘除,最好用移位
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//       test2();

/*
* 只有一个字符的字符串拼接,用''代替""
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//       test3();

/**
* try catch最好不要放在循环里
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//       test4();

/**
* switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//      test5();

/*
* 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省时间
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//      test6();
/*
* 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
* 字符串的分析在很多应用中都是常见的。使用indexOf
* ()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。
* 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//       test7();

/*
* 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//       test8();
/*
* 确定 StringBuffer的容量
* StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小
* ,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
* StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//       test9();
/*
* 尽可能的使用栈变量
*
* 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
* local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//      test10();
/**
* 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
* @author yifangyou
* @since 2011-08-16 09:35:00
*/

//      copyArray();
/*
* 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
//      copyArrayList();
/*
* 复制Map最好用逐个复制最快,putAll最简单
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
copyMap();

}

int localN = 0;
static int staticN = 0;

/*
* 避免在循环条件中使用复杂表达式
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test0() {
ArrayList<Integer> a = new ArrayList<Integer>();

for (int i = 0; i < 10000000; i++) {
a.add(i);
}

long startTime;
// 循环条件中使用复杂表达式
startTime = new Date().getTime();
for (int i = 0; i < a.size(); i++) {
int j = a.get(i);
}
System.out.println(new Date().getTime() - startTime);

// 循环条件中不使用复杂表达式
startTime = new Date().getTime();
for (int i = 0, maxlen = a.size(); i < maxlen; i++) {
int j = a.get(i);
}
System.out.println(new Date().getTime() - startTime);
}

/*
* 如果只是查找单个字符的话,用charAt()代替startsWith()
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test1() {
String s = "sdfsdfsdfsdfdssssssssssssssssssssssssssssdfffffffffffffffa";
long startTime;
// startsWith
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
if (s.startsWith("a")) {

}
}
System.out.println(new Date().getTime() - startTime);
// charAt
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
if (s.charAt(0) == 'a') {

}
}
System.out.println(new Date().getTime() - startTime);

// charAt
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
if ("ab".equals("abcdssdds".substring(0, 2))) {

}
}
System.out.println(new Date().getTime() - startTime);

}

/*
* 能够使用移位的乘除,最好用移位
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test2() {
long startTime;
int a;
//
startTime = new Date().getTime();

for (int i = 0; i < 10000000; i++) {
a = 333333333 / 8;
}
System.out.println(new Date().getTime() - startTime);
// charAt
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
a = 333333333 >> 3;
}
System.out.println(new Date().getTime() - startTime);
}

/*
* 只有一个字符的字符串拼接,用''代替""
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test3() {
long startTime;

startTime = new Date().getTime();
String s = "123";
for (int i = 0; i < 10000000; i++) {
String a = s + "d";
}
System.out.println(new Date().getTime() - startTime);
// charAt
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
String a = s + 'd';
}
System.out.println(new Date().getTime() - startTime);
}

/**
* try catch最好不要放在循环里
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test4() {
long startTime;
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
try {
int a = Integer.parseInt("1");
} catch (Exception e) {

}
}
System.out.println(new Date().getTime() - startTime);

startTime = new Date().getTime();
try {
for (int i = 0; i < 10000000; i++) {
int a = Integer.parseInt("1");
}
} catch (Exception e) {

}

System.out.println(new Date().getTime() - startTime);

}

/**
* switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害,在switch最好把出现次数最多的判断放在最前面
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test5() {
HashMap<String, Integer> types = new HashMap<String, Integer>() {
{
int i = 0;
this.put("a", i++);
this.put("b", i++);
this.put("c", i++);
this.put("d", i++);
this.put("e", i++);
}
};
String a = "e";
int b = 0;
long startTime;
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
if ("a".equals(a)) {
b = 0;
} else if ("b".equals(a)) {
b = 1;
} else if ("c".equals(a)) {
b = 2;
} else if ("d".equals(a)) {
b = 3;
} else if ("e".equals(a)) {
b = 4;
}
}
System.out.println(new Date().getTime() - startTime);

startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
b = types.get(a);
}
System.out.println(new Date().getTime() - startTime);
int c = 14;//改为0的话则最快
startTime = new Date().getTime();
for (int i = 0; i < 10000000; i++) {
switch (c) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
default:
break;
}
}

System.out.println(new Date().getTime() - startTime);
}

/*
* 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省一半时间
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test6() {
StringBuffer s = new StringBuffer("Hello");
int maxlen=1000000;
long startTime;
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
String t =new String("Hello ") + "World!";
}
System.out.println(new Date().getTime() - startTime);

startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
StringBuffer t =new StringBuffer("Hello ").append("World!");
}
System.out.println(new Date().getTime() - startTime);
}

/*
* 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
* 字符串的分析在很多应用中都是常见的。使用indexOf
* ()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。
* 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test7() {
String domain = "www.a.com.";
long startTime;
startTime = new Date().getTime();

for (int i = 0; i < 100000; i++) {
int index = 0;
while ((index = domain.indexOf(".", index + 1)) != -1) {
domain.substring(index + 1, domain.length());
// System.out.println(domain.substring(index+1,
// domain.length()));
}
}
System.out.println(new Date().getTime() - startTime);
startTime = new Date().getTime();
for (int i = 0; i < 100000; i++) {
StringTokenizer st = new StringTokenizer(domain, ".");
while (st.hasMoreTokens()) {
st.nextToken();
// System.out.println(st.nextToken());
}
}
System.out.println(new Date().getTime() - startTime);
}

/*
* 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test8() {
ArrayList<Integer> a = new ArrayList<Integer>();
int maxlen = 10000000;
for (int i = 0; i < maxlen; i++) {
a.add(i);
}
long startTime;
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
Object o = new Object();
o = a.get(i);
}
System.out.println(new Date().getTime() - startTime);
Object o = new Object();
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
o = a.get(i);
}
System.out.println(new Date().getTime() - startTime);
}

/*
* 确定 StringBuffer的容量
* StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存
* ,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
* StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test9() {
int maxlen = 1000000;
long startTime;
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
StringBuffer buffer = new StringBuffer(); // violation
buffer.append("hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
}
System.out.println(new Date().getTime() - startTime);
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
StringBuffer buffer = new StringBuffer(128); // violation
buffer.append("hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
}
System.out.println(new Date().getTime() - startTime);
}

/*
* 尽可能的使用栈变量 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
* local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
public static void test10() {
int maxlen = 100000000;
long startTime;
int n = 0;
Test test = new Test();
// 局部变量
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
n = i;
}
System.out.println(new Date().getTime() - startTime);
// 类变量
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
test.localN = i;
}
System.out.println(new Date().getTime() - startTime);

// 静态变量
startTime = new Date().getTime();
for (int i = 0; i < maxlen; i++) {
Test.staticN = i;
}
System.out.println(new Date().getTime() - startTime);
}
//
//  /*1.尽量使用final修饰符。
//带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。
//   */
//  public static void test11() {
//      int maxlen = 10000000;
//      long startTime;
//      int n = 0;
//
//      // 普通类
//      startTime = new Date().getTime();
//      A a = new A();
//      for (int i = 0; i < maxlen; i++) {
//          a.inc();
//      }
//      System.out.println(new Date().getTime() - startTime);
//
//      // final类
//      startTime = new Date().getTime();
//      FinalA finalA = new FinalA();
//      for (int i = 0; i < maxlen; i++) {
//          finalA.inc();
//      }
//      System.out.println(new Date().getTime() - startTime);
//  }

/**
* 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
static void copyArray() {
int[] array1 = new int[10000000];
int[] array2 = new int[10000000];
for (int i = 0, maxlen = array1.length; i < maxlen; i++) {
array1[i] = i;
}

long startTime;
// 逐个复制,最慢
startTime = new Date().getTime();

for (int i = 0, maxlen = array2.length; i < maxlen; i++) {
array2[i] = array1[i]; // Violation
}
System.out.println(new Date().getTime() - startTime);

// 批量复制,最快
startTime = new Date().getTime();
System.arraycopy(array1, 0, array2, 0, 10000);
System.out.println(new Date().getTime() - startTime);

}

/*
* 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
static void copyArrayList() {
int maxlen = 1000000;
ArrayList<Integer> array1 = new ArrayList<Integer>();
ArrayList<Integer> array2 = new ArrayList<Integer>();
ArrayList<Integer> array3 = new ArrayList<Integer>();
ArrayList<Integer> array4;
for (int i = 0; i < maxlen; i++) {
array1.add(i);
}

long startTime;
// 逐个复制,最慢
startTime = new Date().getTime();

for (int i = 0; i < maxlen; i++) {
array2.add(array1.get(i)); // Violation
}
System.out.println(new Date().getTime() - startTime);

// 批量复制,最快
startTime = new Date().getTime();
array3.addAll(array1);
System.out.println(new Date().getTime() - startTime);

// 克隆,次快
startTime = new Date().getTime();
array4 = (ArrayList<Integer>) array1.clone();
System.out.println(new Date().getTime() - startTime);
array4.set(0, 4);
System.out.println("array1[0]=" + array1.get(0));
System.out.println("array4[0]=" + array4.get(0));

}

/*
* 复制Map最好用逐个复制最快,putAll最简单
* @author yifangyou
* @since 2011-08-16 09:35:00
*/
static void copyMap() {
int maxlen = 1000000;
Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
Map<Integer, Integer> map2 = new HashMap<Integer, Integer>();
Map<Integer, Integer> map3 = new HashMap<Integer, Integer>();
Map<Integer, Integer> map4 = new HashMap<Integer, Integer>();
for (int i = 0; i < maxlen; i++) {
map1.put(i, i);
}

long startTime;
// 逐个复制,最快
startTime = new Date().getTime();
Set<Integer> key = map1.keySet();
for (Iterator it = key.iterator(); it.hasNext();) {
Integer k = (Integer) it.next();
map2.put(k, map1.get(k));
}
System.out.println(new Date().getTime() - startTime);

// 批量复制,最慢
startTime = new Date().getTime();
map3.putAll(map1);
System.out.println(new Date().getTime() - startTime);
System.out.println("map2[9999]=" + map2.get(9999));
System.out.println("map3[9999]=" + map3.get(9999));

// 逐个复制,次快
startTime = new Date().getTime();
Set<Map.Entry<Integer, Integer>> set = map1.entrySet();
for (Iterator<Map.Entry<Integer, Integer>> it = set.iterator(); it
.hasNext();) {
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>) it
.next();
map4.put(entry.getKey(), entry.getValue());
}
System.out.println(new Date().getTime() - startTime);

}

}


本文出自 “一方有” 博客,请务必保留此出处http://yifangyou.blog.51cto.com/900206/641251
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: