Java代碼性能優化小技巧

簡單總結,工作中遇到的問題,僅供參考,如出現任何問題,不接受任何投訴與反駁,哈哈。

雙層循環組合數據篇

業務開發中經常會遇到兩個List

List<Demo1> demo1List;
List<Demo2> demo2List;
for (Demo1 demo1 : demo1List) {
    for (Demo2 demo2 : demo2List) {
        if (demo1.getName.equals(demo2.getName())) {
            demo1.setDemo2(demo2);
        }
    }
}

以上僞代碼存在兩個List,且Demo1 List需要將Demo2 List中的name相同的Demo2合併進來,業務上經常會有這樣的操作,假設Demo1 List大小爲m,Demo2 List大小爲n,則這樣時間符合度則是O(m*n)

當然也有人學會了Stream API會如下實現

List<Demo1> demo1List;
List<Demo2> demo2List;
demo1List.forEach(demo1 -> {
    List<Demo2> demo2FilterList demo2List.stream().filter(demo2 -> demo2.getName().equals(demo1.getName())).collect(Collectors.toList());
    demo1.setDemo2(demo2FilterList.get(0));
})

以上的方式其實複雜度基本沒有任何變化,即使計算開始了stream的parellel,只是利用的多線程優勢,複雜度仍然沒有進步

那……推薦的樣子是什麼呢?如下

List<Demo1> demo1List;
List<Demo2> demo2List;
Map<String, Demo2> demo2Map = demo2List.stream.collect(Collectors.toMap(Demo2::getName, value -> value));
demo1List.forEach(demo1 -> {
    demo1.setDemo2(demo2Map.get(demo1.getName()));
})

以上代碼現將Demo2 List轉換爲key是name、value是Demo2對象,這樣在循環Demo1 List獲取對應Demo2的時候則可以利用Map數據結構複雜度O(1)的特性,此段代碼複雜度則變成O(n+m+m*1),複雜度大大降低

循環內調用IO篇

review過大量的業務代碼,時常會發現有在循環中調用IO的情況,包括不限於訪問數據庫,讀寫文件,甚至訪問Redis等;IO操作是非常耗時的操作,對於大部分的業務系統,系統處理時間大部分都集中在IO處理上,所以應儘量避免此類操作,可採取批量讀取出來,然後再使用上面的組合方法進行優化。

集合應儘量初始化容量使用篇

Java開發中會大量使用集合類,如Map,List等,而這些類大多都是有容量和自動擴容機制的,比如ArrayList的默認容量是10,HashMap的默認容量是16等,當容量達到上限則會自動擴容,擴容則會帶來系統的開銷,ArrayList則需要做數組拷貝,HashMap則需要rehash操作;所以在明確知道需要容量的情況下,可以在初始化階段就指定其容量來減少大量的擴容開銷,這是一個非常實用的優化手段。(注意:HashMap計算實際要使用的容量需要考慮load factor問題,所以推薦使用guava進行初始化操作)

待續…………

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章