Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4173737
  • 博文数量: 291
  • 博客积分: 8003
  • 博客等级: 大校
  • 技术积分: 4275
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-30 18:28
文章分类

全部博文(291)

文章存档

2017年(1)

2013年(47)

2012年(115)

2011年(121)

2010年(7)

分类: Java

2012-03-24 21:19:50

下面的代码是我用来比较代码优化前后的性能

点击(此处)折叠或打开

  1. import java.util.ArrayList;
  2. import java.util.Date;
  3. import java.util.HashMap;
  4. import java.util.Iterator;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.StringTokenizer;
  8.  
  9. public class Test {
  10.  
  11.     public static void main(String argv[]) {
  12.  
  13.         /*
  14.          * 避免在循环条件中使用复杂表达式
  15.          * @author yifangyou
  16.          * @since 2011-08-16 09:35:00
  17.          *
  18.          */
  19. // test0();
  20.         /*
  21.          * 如果只是查找单个字符的话,用charAt()代替startsWith()
  22.          * @author yifangyou
  23.      * @since 2011-08-16 09:35:00
  24.          */
  25. // test1();
  26.  
  27.  
  28.         /*
  29.          * 能够使用移位的乘除,最好用移位
  30.          * @author yifangyou
  31.      * @since 2011-08-16 09:35:00
  32.          */
  33. // test2();
  34.  
  35.         /*
  36.          * 只有一个字符的字符串拼接,用''代替""
  37.          * @author yifangyou
  38.      * @since 2011-08-16 09:35:00
  39.          */
  40. // test3();
  41.  
  42.         /**
  43.          * try catch最好不要放在循环里
  44.          * @author yifangyou
  45.      * @since 2011-08-16 09:35:00
  46.          */
  47. // test4();
  48.  
  49.         /**
  50.          * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害
  51.          * @author yifangyou
  52.      * @since 2011-08-16 09:35:00
  53.          */
  54. // test5();
  55.  
  56.         /*
  57.          * 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省时间
  58.          * @author yifangyou
  59.      * @since 2011-08-16 09:35:00
  60.          */
  61. // test6();
  62.         /*
  63.          * 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
  64.          * 字符串的分析在很多应用中都是常见的。使用indexOf
  65.          * ()和substring()来分析字符串容易导致StringIndexOutOfBound***ception。
  66.          * 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
  67.          * @author yifangyou
  68.      * @since 2011-08-16 09:35:00
  69.          */
  70. // test7();
  71.  
  72.         /*
  73.          * 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
  74.          * @author yifangyou
  75.      * @since 2011-08-16 09:35:00
  76.          */
  77. // test8();
  78.         /*
  79.          * 确定 StringBuffer的容量
  80.          * StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小
  81.          * ,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
  82.          * StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
  83.          * @author yifangyou
  84.      * @since 2011-08-16 09:35:00
  85.          */
  86. // test9();
  87.         /*
  88.          * 尽可能的使用栈变量
  89.          *
  90.          * 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
  91.          * local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
  92.          * @author yifangyou
  93.      * @since 2011-08-16 09:35:00
  94.          */
  95. // test10();
  96.         /**
  97.          * 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
  98.          * @author yifangyou
  99.      * @since 2011-08-16 09:35:00
  100.          */
  101.           
  102. // copyArray();
  103.         /*
  104.          * 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
  105.          * @author yifangyou
  106.      * @since 2011-08-16 09:35:00
  107.          */
  108. // copyArrayList();
  109.         /*
  110.          * 复制Map最好用逐个复制最快,putAll最简单
  111.          * @author yifangyou
  112.      * @since 2011-08-16 09:35:00
  113.          */
  114.         copyMap();
  115.  
  116.       
  117.     }
  118.  
  119.     int localN = 0;
  120.     static int staticN = 0;
  121.  
  122.     /*
  123.      * 避免在循环条件中使用复杂表达式
  124.      * @author yifangyou
  125.      * @since 2011-08-16 09:35:00
  126.      */
  127.     public static void test0() {
  128.         ArrayList<Integer> a = new ArrayList<Integer>();
  129.  
  130.         for (int i = 0; i < 10000000; i++) {
  131.             a.add(i);
  132.         }
  133.  
  134.         long startTime;
  135.         // 循环条件中使用复杂表达式
  136.         startTime = new Date().getTime();
  137.         for (int i = 0; i < a.size(); i++) {
  138.             int j = a.get(i);
  139.         }
  140.         System.out.println(new Date().getTime() - startTime);
  141.  
  142.         // 循环条件中不使用复杂表达式
  143.         startTime = new Date().getTime();
  144.         for (int i = 0, maxlen = a.size(); i < maxlen; i++) {
  145.             int j = a.get(i);
  146.         }
  147.         System.out.println(new Date().getTime() - startTime);
  148.     }
  149.  
  150.     /*
  151.      * 如果只是查找单个字符的话,用charAt()代替startsWith()
  152.      * @author yifangyou
  153.      * @since 2011-08-16 09:35:00
  154.      */
  155.     public static void test1() {
  156.         String s = "sdfsdfsdfsdfdssssssssssssssssssssssssssssdfffffffffffffffa";
  157.         long startTime;
  158.         // startsWith
  159.         startTime = new Date().getTime();
  160.         for (int i = 0; i < 10000000; i++) {
  161.             if (s.startsWith("a")) {
  162.  
  163.             }
  164.         }
  165.         System.out.println(new Date().getTime() - startTime);
  166.         // charAt
  167.         startTime = new Date().getTime();
  168.         for (int i = 0; i < 10000000; i++) {
  169.             if (s.charAt(0) == 'a') {
  170.  
  171.             }
  172.         }
  173.         System.out.println(new Date().getTime() - startTime);
  174.           
  175.         // charAt
  176.         startTime = new Date().getTime();
  177.         for (int i = 0; i < 10000000; i++) {
  178.             if ("ab".equals("abcdssdds".substring(0, 2))) {
  179.  
  180.             }
  181.         }
  182.         System.out.println(new Date().getTime() - startTime);
  183.  
  184.     }
  185.  
  186.     /*
  187.      * 能够使用移位的乘除,最好用移位
  188.      * @author yifangyou
  189.      * @since 2011-08-16 09:35:00
  190.      */
  191.     public static void test2() {
  192.         long startTime;
  193.         int a;
  194.         //
  195.         startTime = new Date().getTime();
  196.  
  197.         for (int i = 0; i < 10000000; i++) {
  198.             a = 333333333 / 8;
  199.         }
  200.         System.out.println(new Date().getTime() - startTime);
  201.         // charAt
  202.         startTime = new Date().getTime();
  203.         for (int i = 0; i < 10000000; i++) {
  204.             a = 333333333 >> 3;
  205.         }
  206.         System.out.println(new Date().getTime() - startTime);
  207.     }
  208.  
  209.     /*
  210.      * 只有一个字符的字符串拼接,用''代替""
  211.      * @author yifangyou
  212.      * @since 2011-08-16 09:35:00
  213.      */
  214.     public static void test3() {
  215.         long startTime;
  216.  
  217.         startTime = new Date().getTime();
  218.         String s = "123";
  219.         for (int i = 0; i < 10000000; i++) {
  220.             String a = s + "d";
  221.         }
  222.         System.out.println(new Date().getTime() - startTime);
  223.         // charAt
  224.         startTime = new Date().getTime();
  225.         for (int i = 0; i < 10000000; i++) {
  226.             String a = s + 'd';
  227.         }
  228.         System.out.println(new Date().getTime() - startTime);
  229.     }
  230.  
  231.     /**
  232.      * try catch最好不要放在循环里
  233.      * @author yifangyou
  234.      * @since 2011-08-16 09:35:00
  235.      */
  236.     public static void test4() {
  237.         long startTime;
  238.         startTime = new Date().getTime();
  239.         for (int i = 0; i < 10000000; i++) {
  240.             try {
  241.                 int a = Integer.parseInt("1");
  242.             } catch (Exception e) {
  243.  
  244.             }
  245.         }
  246.         System.out.println(new Date().getTime() - startTime);
  247.  
  248.         startTime = new Date().getTime();
  249.         try {
  250.             for (int i = 0; i < 10000000; i++) {
  251.                 int a = Integer.parseInt("1");
  252.             }
  253.         } catch (Exception e) {
  254.  
  255.         }
  256.  
  257.         System.out.println(new Date().getTime() - startTime);
  258.  
  259.     }
  260.  
  261.     /**
  262.      * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害,在switch最好把出现次数最多的判断放在最前面
  263.      * @author yifangyou
  264.      * @since 2011-08-16 09:35:00
  265.      */
  266.     public static void test5() {
  267.         HashMap<String, Integer> types = new HashMap<String, Integer>() {
  268.             {
  269.                 int i = 0;
  270.                 this.put("a", i++);
  271.                 this.put("b", i++);
  272.                 this.put("c", i++);
  273.                 this.put("d", i++);
  274.                 this.put("e", i++);
  275.             }
  276.         };
  277.         String a = "e";
  278.         int b = 0;
  279.         long startTime;
  280.         startTime = new Date().getTime();
  281.         for (int i = 0; i < 10000000; i++) {
  282.             if ("a".equals(a)) {
  283.                 b = 0;
  284.             } else if ("b".equals(a)) {
  285.                 b = 1;
  286.             } else if ("c".equals(a)) {
  287.                 b = 2;
  288.             } else if ("d".equals(a)) {
  289.                 b = 3;
  290.             } else if ("e".equals(a)) {
  291.                 b = 4;
  292.             }
  293.         }
  294.         System.out.println(new Date().getTime() - startTime);
  295.  
  296.         startTime = new Date().getTime();
  297.         for (int i = 0; i < 10000000; i++) {
  298.             b = types.get(a);
  299.         }
  300.         System.out.println(new Date().getTime() - startTime);
  301.         int c = 14;//改为0的话则最快
  302.         startTime = new Date().getTime();
  303.         for (int i = 0; i < 10000000; i++) {
  304.             switch (c) {
  305.             case 0:
  306.                 break;
  307.             case 1:
  308.                 break;
  309.             case 2:
  310.                 break;
  311.             case 3:
  312.                 break;
  313.             case 4:
  314.                 break;
  315.             case 5:
  316.                 break;
  317.             case 6:
  318.                 break;
  319.             case 7:
  320.                 break;
  321.             case 8:
  322.                 break;
  323.             case 9:
  324.                 break;
  325.             case 10:
  326.                 break;
  327.             case 11:
  328.                 break;
  329.             case 12:
  330.                 break;
  331.             case 13:
  332.                 break;
  333.             case 14:
  334.                 break;
  335.             default:
  336.                 break;
  337.             }
  338.         }
  339.  
  340.         System.out.println(new Date().getTime() - startTime);
  341.     }
  342.  
  343.     /*
  344.      * 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省一半时间
  345.      * @author yifangyou
  346.      * @since 2011-08-16 09:35:00
  347.      */
  348.     public static void test6() {
  349.         StringBuffer s = new StringBuffer("Hello");
  350.         int maxlen=1000000;
  351.         long startTime;
  352.         startTime = new Date().getTime();
  353.         for (int i = 0; i < maxlen; i++) {
  354.             String t =new String("Hello ") + "World!";
  355.         }
  356.         System.out.println(new Date().getTime() - startTime);
  357.           
  358.         startTime = new Date().getTime();
  359.         for (int i = 0; i < maxlen; i++) {
  360.             StringBuffer t =new StringBuffer("Hello ").append("World!");
  361.         }
  362.         System.out.println(new Date().getTime() - startTime);
  363.     }
  364.  
  365.     /*
  366.      * 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
  367.      * 字符串的分析在很多应用中都是常见的。使用indexOf
  368.      * ()和substring()来分析字符串容易导致StringIndexOutOfBound***ception。
  369.      * 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
  370.      * @author yifangyou
  371.      * @since 2011-08-16 09:35:00
  372.      */
  373.     public static void test7() {
  374.         String domain = "";
  375.         long startTime;
  376.         startTime = new Date().getTime();
  377.  
  378.         for (int i = 0; i < 100000; i++) {
  379.             int index = 0;
  380.             while ((index = domain.indexOf(".", index + 1)) != -1) {
  381.                 domain.substring(index + 1, domain.length());
  382.                 // System.out.println(domain.substring(index+1,
  383.                 // domain.length()));
  384.             }
  385.         }
  386.         System.out.println(new Date().getTime() - startTime);
  387.         startTime = new Date().getTime();
  388.         for (int i = 0; i < 100000; i++) {
  389.             StringTokenizer st = new StringTokenizer(domain, ".");
  390.             while (st.hasMoreTokens()) {
  391.                 st.nextToken();
  392.                 // System.out.println(st.nextToken());
  393.             }
  394.         }
  395.         System.out.println(new Date().getTime() - startTime);
  396.     }
  397.  
  398.     /*
  399.      * 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
  400.      * @author yifangyou
  401.      * @since 2011-08-16 09:35:00
  402.      */
  403.     public static void test8() {
  404.         ArrayList<Integer> a = new ArrayList<Integer>();
  405.         int maxlen = 10000000;
  406.         for (int i = 0; i < maxlen; i++) {
  407.             a.add(i);
  408.         }
  409.         long startTime;
  410.         startTime = new Date().getTime();
  411.         for (int i = 0; i < maxlen; i++) {
  412.             Object o = new Object();
  413.             o = a.get(i);
  414.         }
  415.         System.out.println(new Date().getTime() - startTime);
  416.         Object o = new Object();
  417.         startTime = new Date().getTime();
  418.         for (int i = 0; i < maxlen; i++) {
  419.             o = a.get(i);
  420.         }
  421.         System.out.println(new Date().getTime() - startTime);
  422.     }
  423.  
  424.     /*
  425.      * 确定 StringBuffer的容量
  426.      * StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存
  427.      * ,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
  428.      * StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
  429.      * @author yifangyou
  430.      * @since 2011-08-16 09:35:00
  431.      */
  432.     public static void test9() {
  433.         int maxlen = 1000000;
  434.         long startTime;
  435.         startTime = new Date().getTime();
  436.         for (int i = 0; i < maxlen; i++) {
  437.             StringBuffer buffer = new StringBuffer(); // violation
  438.             buffer.append("hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  439.         }
  440.         System.out.println(new Date().getTime() - startTime);
  441.         startTime = new Date().getTime();
  442.         for (int i = 0; i < maxlen; i++) {
  443.             StringBuffer buffer = new StringBuffer(128); // violation
  444.             buffer.append("hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  445.         }
  446.         System.out.println(new Date().getTime() - startTime);
  447.     }
  448.  
  449.     /*
  450.      * 尽可能的使用栈变量 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
  451.      * local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
  452.      * @author yifangyou
  453.      * @since 2011-08-16 09:35:00
  454.      */
  455.     public static void test10() {
  456.         int maxlen = 100000000;
  457.         long startTime;
  458.         int n = 0;
  459.         Test test = new Test();
  460.         // 局部变量
  461.         startTime = new Date().getTime();
  462.         for (int i = 0; i < maxlen; i++) {
  463.             n = i;
  464.         }
  465.         System.out.println(new Date().getTime() - startTime);
  466.         // 类变量
  467.         startTime = new Date().getTime();
  468.         for (int i = 0; i < maxlen; i++) {
  469.             test.localN = i;
  470.         }
  471.         System.out.println(new Date().getTime() - startTime);
  472.  
  473.         // 静态变量
  474.         startTime = new Date().getTime();
  475.         for (int i = 0; i < maxlen; i++) {
  476.             Test.staticN = i;
  477.         }
  478.         System.out.println(new Date().getTime() - startTime);
  479.     }
  480. //
  481. // /*1.尽量使用final修饰符。
  482. //带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。
  483. // */
  484. // public static void test11() {
  485. // int maxlen = 10000000;
  486. // long startTime;
  487. // int n = 0;
  488. //
  489. // // 普通类
  490. // startTime = new Date().getTime();
  491. // A a = new A();
  492. // for (int i = 0; i < maxlen; i++) {
  493. // a.inc();
  494. // }
  495. // System.out.println(new Date().getTime() - startTime);
  496. //
  497. // // final类
  498. // startTime = new Date().getTime();
  499. // FinalA finalA = new FinalA();
  500. // for (int i = 0; i < maxlen; i++) {
  501. // finalA.inc();
  502. // }
  503. // System.out.println(new Date().getTime() - startTime);
  504. // }
  505.  
  506.     /**
  507.      * 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
  508.      * @author yifangyou
  509.      * @since 2011-08-16 09:35:00
  510.      */
  511.     static void copyArray() {
  512.         int[] array1 = new int[10000000];
  513.         int[] array2 = new int[10000000];
  514.         for (int i = 0, maxlen = array1.length; i < maxlen; i++) {
  515.             array1[i] = i;
  516.         }
  517.  
  518.         long startTime;
  519.         // 逐个复制,最慢
  520.         startTime = new Date().getTime();
  521.  
  522.         for (int i = 0, maxlen = array2.length; i < maxlen; i++) {
  523.             array2[i] = array1[i]; // Violation
  524.         }
  525.         System.out.println(new Date().getTime() - startTime);
  526.  
  527.         // 批量复制,最快
  528.         startTime = new Date().getTime();
  529.         System.arraycopy(array1, 0, array2, 0, 10000);
  530.         System.out.println(new Date().getTime() - startTime);
  531.  
  532.     }
  533.  
  534.     /*
  535.      * 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
  536.      * @author yifangyou
  537.      * @since 2011-08-16 09:35:00
  538.      */
  539.     static void copyArrayList() {
  540.         int maxlen = 1000000;
  541.         ArrayList<Integer> array1 = new ArrayList<Integer>();
  542.         ArrayList<Integer> array2 = new ArrayList<Integer>();
  543.         ArrayList<Integer> array3 = new ArrayList<Integer>();
  544.         ArrayList<Integer> array4;
  545.         for (int i = 0; i < maxlen; i++) {
  546.             array1.add(i);
  547.         }
  548.  
  549.         long startTime;
  550.         // 逐个复制,最慢
  551.         startTime = new Date().getTime();
  552.  
  553.         for (int i = 0; i < maxlen; i++) {
  554.             array2.add(array1.get(i)); // Violation
  555.         }
  556.         System.out.println(new Date().getTime() - startTime);
  557.  
  558.         // 批量复制,最快
  559.         startTime = new Date().getTime();
  560.         array3.addAll(array1);
  561.         System.out.println(new Date().getTime() - startTime);
  562.  
  563.         // 克隆,次快
  564.         startTime = new Date().getTime();
  565.         array4 = (ArrayList<Integer>) array1.clone();
  566.         System.out.println(new Date().getTime() - startTime);
  567.         array4.set(0, 4);
  568.         System.out.println("array1[0]=" + array1.get(0));
  569.         System.out.println("array4[0]=" + array4.get(0));
  570.  
  571.     }
  572.  
  573.     /*
  574.      * 复制Map最好用逐个复制最快,putAll最简单
  575.      * @author yifangyou
  576.      * @since 2011-08-16 09:35:00
  577.      */
  578.     static void copyMap() {
  579.         int maxlen = 1000000;
  580.         Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
  581.         Map<Integer, Integer> map2 = new HashMap<Integer, Integer>();
  582.         Map<Integer, Integer> map3 = new HashMap<Integer, Integer>();
  583.         Map<Integer, Integer> map4 = new HashMap<Integer, Integer>();
  584.         for (int i = 0; i < maxlen; i++) {
  585.             map1.put(i, i);
  586.         }
  587.  
  588.         long startTime;
  589.         // 逐个复制,最快
  590.         startTime = new Date().getTime();
  591.         Set<Integer> key = map1.keySet();
  592.         for (Iterator it = key.iterator(); it.hasNext();) {
  593.             Integer k = (Integer) it.next();
  594.             map2.put(k, map1.get(k));
  595.         }
  596.         System.out.println(new Date().getTime() - startTime);
  597.  
  598.         // 批量复制,最慢
  599.         startTime = new Date().getTime();
  600.         map3.putAll(map1);
  601.         System.out.println(new Date().getTime() - startTime);
  602.         System.out.println("map2[9999]=" + map2.get(9999));
  603.         System.out.println("map3[9999]=" + map3.get(9999));
  604.  
  605.         // 逐个复制,次快
  606.         startTime = new Date().getTime();
  607.         Set<Map.Entry<Integer, Integer>> set = map1.entrySet();
  608.         for (Iterator<Map.Entry<Integer, Integer>> it = set.iterator(); it
  609.                 .hasNext();) {
  610.             Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>) it
  611.                     .next();
  612.             map4.put(entry.getKey(), entry.getValue());
  613.         }
  614.         System.out.println(new Date().getTime() - startTime);
  615.  
  616.     }
  617.  
  618. }

阅读(2052) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~