java代码优化前后性能对比测试
2011-08-17 11:40
483 查看
下面的代码是我用来比较代码优化前后的性能
本文出自 “一方有” 博客,请务必保留此出处http://yifangyou.blog.51cto.com/900206/641251
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
相关文章推荐
- Java 7新特性及简单性能对比测试
- go语言和java+jetty的web hello world 性能测试对比
- Java中字符串操作类String、StringBuffer、StringBuilder区别及性能对比测试
- 常用Java性能测试工具的分析与对比
- 常用Java性能测试工具的分析与对比
- 常用Java性能测试工具的分析与对比
- groovy性能测试,groovy和java性能对比
- java对比IO和NIO的文件读写性能测试
- java对比IO和NIO的文件读写性能测试
- Java 7新特性及简单性能对比测试
- 性能报告 DotNet测试MYSQL报告(和Java对比)
- mysql性能测试(使用TCMalloc前后对比)
- 性能测试脚本开发(C&C#&Java)
- JAVA反射性能测试及对架构工作的一些思考
- java性能测试,追踪,优化Eclipse 插件系列之 TPTP for Galileo 3.5.x
- redis 集群性能测试以及与单机性能对比
- Chrome浏览器性能对比测试报告
- Java中的HashMap和ConcurrentHashMap的并发性能测试
- loadrunner使用JavaVuser协议测试API接口性能
- 【转载】Java中将InputStream读取为String, 各种方法的性能对比