成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

項目里用到 Java 集合時,應該避免的一些坑

開發 后端
前不久幫同事一起 review 一個 job 執行緩慢的問題時發現不少朋友在擼碼實現功能時還是有需要細節不夠注意,于是便有了這篇文章。

 前言

前不久幫同事一起 review 一個 job 執行緩慢的問題時發現不少朋友在擼碼實現功能時還是有需要細節不夠注意,于是便有了這篇文章。

[[313003]]

ArrayList 踩坑

  1. List<String> temp = new ArrayList() ;//獲取一批數據List<String> all = getData();for(String str : all) {    temp.add(str);} 

首先大家看看這段代碼有什么問題嘛?

其實在大部分情況下這都是沒啥問題,無非就是循環的往 ArrayList 中寫入數據而已。

但在特殊情況下,比如這里的 getData() 返回數據非常巨大時后續 temp.add(str) 就會有問題了。

比如我們在 review 代碼時發現這里返回的數據有時會高達 2000W,這時 ArrayList 寫入的問題就凸顯出來了。

填坑指南

大家都知道 ArrayList 是由數組實現,而數據的長度有限;需要在合適的時機對數組擴容。

這里以插入到尾部為例 add(E e)。

 

項目里用到 Java 集合時,應該避免的一些坑
  1. ArrayListtemp=newArrayList<>(2);temp.add("1");temp.add("2");temp.add("3"); 

當我們初始化一個長度為 2 的 ArrayList ,并往里邊寫入三條數據時 ArrayList 就得擴容了,也就是將之前的數據復制一份到新的數組長度為 3 的數組中。

 

項目里用到 Java 集合時,應該避免的一些坑

 

之所以是 3 ,是因為新的長度=原有長度 * 1.5

通過源碼我們可以得知 ArrayList 的默認長度為 10.

 

項目里用到 Java 集合時,應該避免的一些坑

 

 

項目里用到 Java 集合時,應該避免的一些坑

 

但其實并不是在初始化的時候就創建了 DEFAULT_CAPACITY=10 的數組。

 

項目里用到 Java 集合時,應該避免的一些坑

 

而是在往里邊 add 第一個數據的時候會擴容到 10.

既然知道了默認的長度為 10 ,那說明后續一旦寫入到第九個元素的時候就會擴容為 10*1.5=15。這一步為數組復制,也就是要重新開辟一塊新的內存空間存放這 15 個數組。

一旦我們頻繁且數量巨大的進行寫入時就會導致許多的數組復制,這個效率是極低的。

但如果我們提前預知了可能會寫入多少條數據時就可以提前避免這個問題。

比如我們往里邊寫入 1000W 條數據,在初始化的時候就給定數組長度與用默認 10 的長度之間性能是差距巨大的。

我用 JMH 基準測試驗證如下:

  1. @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)public class CollectionsTest {    private static final int TEN_MILLION = 10000000;    @Benchmark    @BenchmarkMode(Mode.AverageTime)    @OutputTimeUnit(TimeUnit.MICROSECONDS)    public void arrayList() {        List<String> array = new ArrayList<>();        for (int i = 0; i < TEN_MILLION; i++) {            array.add("123");        }    }    @Benchmark    @BenchmarkMode(Mode.AverageTime)    @OutputTimeUnit(TimeUnit.MICROSECONDS)    public void arrayListSize() {        List<String> array = new ArrayList<>(TEN_MILLION);        for (int i = 0; i < TEN_MILLION; i++) {            array.add("123");        }    }    public static void main(String[] args) throws RunnerException {        Options opt = new OptionsBuilder()                .include(CollectionsTest.class.getSimpleName())                .forks(1)                .build();        new Runner(opt).run();    }} 

 

項目里用到 Java 集合時,應該避免的一些坑

 

根據結果可以看出預設長度的效率會比用默認的效率高上很多(這里的 Score 指執行完函數所消耗的時間)。

所以這里強烈建議大家:在有大量數據寫入 ArrayList 時,一定要初始化指定長度。

再一個是一定要慎用 add(intindex,E element) 向指定位置寫入數據。

 

項目里用到 Java 集合時,應該避免的一些坑

 

通過源碼我們可以看出,每一次寫入都會將 index 后的數據往后移動一遍,其實本質也是要復制數組;

但區別于往常規的往數組尾部寫入數據,它每次都會進行數組復制,效率極低。

LinkedList

提到 ArrayList 就不得不聊下 LinkedList 這個孿生兄弟;雖說都是 List 的容器,但本質實現卻完全不同。

 

項目里用到 Java 集合時,應該避免的一些坑

 

LinkedList 是由鏈表組成,每個節點又有頭尾兩個節點分別引用了前后兩個節點;因此它也是一個雙向鏈表。

所以理論上來說它的寫入非常高效,將不會有 ArrayList 中效率極低的數組復制,每次只需要移動指針即可。

這里偷懶就不畫圖了,大家自行腦補下。

對比測試

坊間一直流傳:

LinkedList 的寫入效率高于 ArrayList,所以在寫大于讀的時候非常適用于 LinkedList 。

  1. @Benchmark    @BenchmarkMode(Mode.AverageTime)    @OutputTimeUnit(TimeUnit.MICROSECONDS)    public void linkedList() {        List<String> array = new LinkedList<>();        for (int i = 0; i < TEN_MILLION; i++) {            array.add("123");        }    } 

 

項目里用到 Java 集合時,應該避免的一些坑

 

這里測試看下結論是否符合;同樣的也是對 LinkedList 寫入 1000W 次數據,通過結果來看初始化數組長度的 ArrayList 效率明顯是要高于 LinkedList 。

但這里的前提是要提前預設 ArrayList 的數組長度,避免數組擴容,這樣 ArrayList 的寫入效率是非常高的,而 LinkedList 的雖然不需要復制內存,但卻需要創建對象,變換指針等操作。

而查詢就不用多說了, ArrayList 可以支持下標隨機訪問,效率非常高。

LinkedList 由于底層不是數組,不支持通過下標訪問,而是需要根據查詢 index 所在的位置來判斷是從頭還是從尾進行遍歷。

 

項目里用到 Java 集合時,應該避免的一些坑

 

但不管是哪種都得需要移動指針來一個個遍歷,特別是 index 靠近中間位置時將會非常慢。

 

總結

高性能應用都是從小細節一點點堆砌起來的,就如這里提到的 ArrayList 的坑一樣,日常使用沒啥大問題,一旦數據量起來所有的小問題都會成為大問題。

所以再總結下:

  • 再使用 ArrayList 時如果能提前預測到數據量大小,比較大時一定要指定其長度。
  • 盡可能避免使用 add(index,e) api,會導致復制數組,降低效率。
  • 再額外提一點,我們常用的另一個 Map 容器 HashMap 也是推薦要初始化長度從而避免擴容。

 

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2022-12-27 14:52:31

Kubernetes云原生開發

2021-06-08 06:13:16

React開發開發技術

2021-06-30 07:19:35

微服務業務MySQL

2010-10-08 16:32:59

MySQL語句

2019-07-11 10:42:57

容器ArrayList JMH

2019-07-10 08:56:50

Java技術容器

2021-04-16 08:11:24

js前端JavaScript

2020-08-07 08:04:03

數據庫MySQL技術

2018-05-30 12:04:36

LinuxUbuntu 18.0

2010-06-11 09:19:23

jQuery

2023-03-28 08:14:42

系統優化指標

2014-08-07 09:40:46

2018-03-26 20:00:32

深度學習

2011-08-01 10:37:29

軟件項目管理

2011-06-01 16:50:21

JAVA

2012-11-05 10:35:59

程序員程序發布程序BUG

2012-11-05 10:17:33

編程開發程序

2015-08-24 09:26:18

Java內存問題見解

2015-12-08 09:05:41

Java內部類

2009-06-22 15:36:00

如何學好java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲福利 | av毛片在线免费观看 | 国产欧美日韩精品一区 | 欧美一二三 | a中文在线视频 | 国产一区二区三区日韩 | 国产精品久久久爽爽爽麻豆色哟哟 | 久久国产精品72免费观看 | 国产亚洲一区二区三区 | 欧美黄 片免费观看 | 日韩视频a | 福利片在线 | 免费观看一区二区三区毛片 | 国产激情一区二区三区 | 国产日韩欧美精品 | 久久午夜精品福利一区二区 | 男人的天堂在线视频 | 天天综合网永久 | 日本三级全黄三级a | av在线视 | 精品粉嫩超白一线天av | 日韩精品视频一区二区三区 | 亚洲精品久 | 欧美日韩精品 | 欧美一区二区三区在线 | 精品国产视频 | 91中文字幕在线观看 | 91精品国产乱码久久久久久久 | 成人亚洲精品久久久久软件 | 欧美成人精品 | av黄色免费在线观看 | 日韩人体在线 | 欧美日韩精品一区二区天天拍 | 午夜免费网站 | a视频在线观看 | 色在线免费视频 | 一级a性色生活片久久毛片 一级特黄a大片 | 亚洲高清在线观看 | 日韩在线电影 | 天久久 | 国产成人aⅴ |