• JDK源码分析——性能优化实例


    1、尽可能的用位运算,比如HashMap的查找Entry<K, V> [] table下标的操作
    static int indexFor(int h, int length) {
        
    return h & (length-1);
    }

    2、对于java.utl.ArrayList、HashMap、LinkedHashMap、HashSet、LinkedSet等的new操作最好指定所需大小。
        2.1、对于ArrayList来说add操作有一行代码为:ensureCapacity(size + 1);具体实现如下:
     1 public void ensureCapacity(int minCapacity) {
     2     modCount++;
     3     int oldCapacity = elementData.length;
     4     if (minCapacity > oldCapacity) {
     5         Object oldData[] = elementData;
     6         int newCapacity = (oldCapacity * 3)/2 + 1;
     7             if (newCapacity < minCapacity)
     8         newCapacity = minCapacity;
     9             // minCapacity is usually close to size, so this is a win:
    10             elementData = Arrays.copyOf(elementData, newCapacity);
    11     }
    12 }
        可以看出,如果ArrayList超出原先的容量,需要扩容的时候,是先new一个数组,然后把原来的数组拷贝到新数组中。所以如果原先可以确定容量的话,采用public ArrayList(int initialCapacity)构造方法。

        2.2、对于HashMap来说put操作,如果在原有的key中没有找到匹配项,则需要把key加入到Entry<>[] table中。        具体代码如下:
    1 void addEntry(int hash, K key, V value, int bucketIndex) {
    2     Entry<K,V> e = table[bucketIndex];
    3     table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    4     if (size++ >= threshold)
    5         // 当size++ >= 负载因子时,进行扩容操作
    6         resize(2 * table.length);
    7 }
      resize(int newCapacity)代码如下:
     1 void resize(int newCapacity) {
     2     Entry[] oldTable = table;
     3     int oldCapacity = oldTable.length;
     4     if (oldCapacity == MAXIMUM_CAPACITY) {
     5         threshold = Integer.MAX_VALUE;
     6         return;
     7     }
     8     // 需要重新new 一个Entry数组
     9     Entry[] newTable = new Entry[newCapacity];
    10     transfer(newTable);
    11     table = newTable;
    12     threshold = (int)(newCapacity * loadFactor);
    13 }
    这里调用一个方法transfer(Entry[] newTable)其代码如下:
     1 void transfer(Entry[] newTable) {
     2     Entry[] src = table;
     3     int newCapacity = newTable.length;
     4     // 对Entry[] src进行循环,把旧的Entry[]拷贝到新的Entry[]中
     5     for (int j = 0; j < src.length; j++) {
     6         Entry<K,V> e = src[j];
     7         if (e != null) {
     8             // 把src赋值为null,为了GC操作的时候,回收原来的Entry[]
     9             src[j] = null;
    10             // 对table[j]的链表进行循环
    11             do {
    12                 Entry<K,V> next = e.next;
    13                 // 计算在新的Entry[]数组的下标
    14                 int i = indexFor(e.hash, newCapacity);
    15                 
    16                 e.next = newTable[i];
    17                 newTable[i] = e;
    18                 e = next;
    19             } while (e != null);
    20         }
    21     }
    22 }
        2.3、HashSet、LinkedSet、LinkedMap与上同

    3、数组复制的时候,用System.arraycopy方法,比如2.1中的ensureCapacity(int minCapacity)方法,调用的Arrays.copyOf方法。在Array.copy中调用了System.arraycopy,其代码如下:
    1 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    2     T[] copy = ((Object)newType == (Object)Object[].class)
    3         ? (T[]) new Object[newLength]
    4         : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    5     System.arraycopy(original, 0, copy, 0,
    6                      Math.min(original.length, newLength));
    7     return copy;
    8 }
  • 相关阅读:
    TRichView文档结构2
    Qtablewidget 复杂表头
    Qwt 使用mingw编译安装过程(windows):
    [转]为什么有的人工作多年还是老样子?
    软件公司书籍推荐——按角色划分
    Qt error: one or more PCH files were found, but they were invalid
    qt5.5程序打包发布以及依赖【转】
    Qt5.5.1编译出来的程序出现libgcc_s_dw2-1.dll的解决方案
    值得推荐的C/C++框架和库
    开发资源汇总
  • 原文地址:https://www.cnblogs.com/daichangya/p/12960043.html
Copyright © 2020-2023  润新知