• 影响Java代码性能的一些细节


      读《Effective Java》的一些收获,会持续添加。

      Integer和 int的区别:

      int是 Java基本数据类型,表示一个整型值。Integer是对 int基本类型的一个封装(每一个 Integer对象中都包含一个"private final int value;"的成员变量),提供了一系列的通用方法,如 int与 String的相互转换,把 int值转换为 long、char等其他基本类型。相应地,两个封装了相同的 int值的 Integer对象在使用"=="比较的时候不一定会返回 true。例如下边的代码 b的值为 false:

      boolean b = new Integer(10) == new Integer(10);

      Integer类实现了 Comparable接口,具体的实现方法是比较两个 Integer对象封装的 int值:

      public int compareTo(Integer anotherInteger) {
          return compare(this.value, anotherInteger.value);
      }
    
      public static int compare(int x, int y) {
          return (x < y) ? -1 : ((x == y) ? 0 : 1);
      }

      通过看 Integer的源码我们可以发现,除了包含一个 value成员变量,其他都是 static的成员和方法,这些不会导致性能问题。Integer类所带来的性能问题主要来自于创建 Integer对象的开销,例如:

        public static void main(String[] args) throws InterruptedException {
            
            long sum = 0L;
            
            long start = System.currentTimeMillis();
            for (long i = 0; i < Integer.MAX_VALUE; i++) {
                sum += i;
            }
            long end = System.currentTimeMillis();
            long time = (end - start) / 1000L;
            
            System.out.println("time=" + time);
        }

      运行这段代码,结果是 time=1,如果把 sum定义为 Long型,结果是 time=10。这提示我们除非集合和参数化类型等必要情况下,其他时候应该尽可能少使用 Integer等包装类。

      使用 StringBuilder.append()方法和"+"对字符串进行连接:

        public String statement() {
            String result = "";
            for (int i = 0; i < 10000; i++) {
                result += "哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈";
            }
         return result; }

      上述这段代码,在读第51条之前,我认为在十几毫秒时间内可以执行完成,仍使用 System.currentTimeMillis()打印执行时间,结果是 time=4。把次数改为20000,time=16。改为100000,结果time=486。改为1000000,博文都快写完了,还没跑出来结果..

      看到这里稍微有些编程经验的人都大概会才出来是 Java内部使用了迭代导致开销呈平方级的增长,那"+"操作到底做了什么会在内部使用迭代呢?(编译源码来源:CSDN-zcjl)

       0:   ldc     #2; //String result
       2:   astore_1
       3:   iconst_0
       4:   istore_2
       5:   iload_2
       6:   bipush  10000
       8:   if_icmpge       36
       11:  new     #3; //class StringBuffer
       14:  dup
       15:  invokespecial   #4; //Method java/lang/StringBuffer."<init>":()V
       18:  aload_1
       19:  invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
       22:  iload_2
       23:  invokevirtual   #6; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
       26:  invokevirtual   #7; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
       29:  astore_1
       30:  iinc    2, 1
       33:  goto    5
       36:  return

      我们可以看第11行,在每次进行"+"操作的时候,都会 new一个 StringBuilder对象来实现字符串的拼装。

      这也是为什么在拼装操作次数未知的情况下,推荐使用 StringBuilder.append()方法的原因。

  • 相关阅读:
    XML
    编码格式
    CSS 实现加载动画之七-彩环旋转
    CSS 实现加载动画之六-大风车
    CSS 实现加载动画之五-光盘旋转
    CSS 实现加载动画之四-圆点旋转
    CSS 实现加载动画之三-钢琴按键
    CSS 实现加载动画之二-圆环旋转
    CSS 实现加载动画之一-菊花旋转
    JS案例之8——从一个数组中随机取数
  • 原文地址:https://www.cnblogs.com/haitong/p/3751930.html
Copyright © 2020-2023  润新知