国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|

服務器之家 - 編程語言 - JAVA教程 - Java ArrayList 實現實例講解

Java ArrayList 實現實例講解

2020-06-30 11:05有女朋友的程序猿 JAVA教程

ArrayList是基于數組實現的,是一個動態數組,其容量能自動增長,類似于C語言中的動態申請內存,動態增長內存。這篇文章主要介紹了java ArrayList 實現的相關資料,需要的朋友可以參考下

 ArrayList概述: 

ArrayList是基于數組實現的,是一個動態數組,其容量能自動增長,類似于C語言中的動態申請內存,動態增長內存。

    ArrayList不是線程安全的,只能用在單線程環境下,多線程環境下可以考慮用Collections.synchronizedList(List l)函數返回一個線程安全的ArrayList類,也可以使用concurrent并發包下的CopyOnWriteArrayList類。

    ArrayList實現了Serializable接口,因此它支持序列化,能夠通過序列化傳輸,實現了RandomAccess接口,支持快速隨機訪問,實際上就是通過下標序號進行快速訪問,實現了Cloneable接口,能被克隆。

   每個ArrayList實例都有一個容量,該容量是指用來存儲列表元素的數組的大小。它總是至少等于列表的大小。隨著向ArrayList中不斷添加元素,其容量也自動增長。自動增長會帶來數據向新數組的重新拷貝,因此,如果可預知數據量的多少,可在構造ArrayList時指定其容量。在添加大量元素前,應用程序也可以使用ensureCapacity操作來增加ArrayList實例的容量,這可以減少遞增式再分配的數量。 

   注意,此實現不是同步的。如果多個線程同時訪問一個ArrayList實例,而其中至少一個線程從結構上修改了列表,那么它必須保持外部同步。

下面對java arraylist做一個記錄和總結吧

?
1
2
3
4
5
6
7
8
public class arraylist<E> {
  /**
   * 存放集合的元素
   *
   */
  private transient Object[] elementData;
  /** 元素的大小 */
  private int size;

定義了一個泛型類,一個object的數組和一個私有變量來記錄該集合的元素數量,原文多了一個私有變量,我也不知道干嘛用的,作者也沒解釋也沒提及到,我沒使用也沒事

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
   * 根據指定大小初始化
   * @param initialCapacity
   */
  public arraylist(int initialCapacity){
    super();
    if(initialCapacity<=0){
      //拋異常
      throw new IllegalArgumentException("初始化參數不能小于0");
    }else{
      //初始化數組
      this.elementData=new Object[initialCapacity];
    }
  }
  /**
   * 默認初始化
   */
  public arraylist(){
    this(10);
  }
  /**
   * 根據一個集合類初始化
   * @param c 一個必須繼承了Collection接口的類
   */
  public arraylist(Collection<? extends E> c){
    //初始化
    elementData=c.toArray();
    size=elementData.length;
    //如果不是任意類型的數組就轉換Objec類型
    if (elementData.getClass() != Object[].class){
      elementData=Arrays.copyOf(elementData,size, Object[].class);
    }
  }

3個初始化方法,根據默認大小進行數組的初始化,給定大小初始化和傳遞一個繼承了Collection集合接口的類進行轉換賦值初始化

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
   * 擴容集合
   * @param minCapacity
   */
  public void ensureCapacity(int minCapacity){
    /** 當前數組的大小 */
    int oldCapacity = elementData.length;
    if (minCapacity > oldCapacity) {
      /**
       * oldData 雖然沒有被使用,但是這是關于內存管理的原因和Arrays.copyOf()方法不是線程安全
       * oldData在if的生命周期內引用elementData這個變量,所以不會被GC回收掉
       * 當Arrays.copyOf()方法在把elementData復制到newCapacity時,就可以防止新的內存或是其他線程分配內存是elementData內存被侵占修改
       * 當結束是離開if,oldData周期就結束被回收
       */
      Object oldData[] = elementData;
      int newCapacity = (oldCapacity * 3)/2 + 1; //增加50%+1
        if (newCapacity < minCapacity)
          newCapacity = minCapacity;
     //使用Arrays.copyOf把集合的元素復制并生成一個新的數組
     elementData = Arrays.copyOf(elementData, newCapacity);
    }
  }

這是一個核心的方法,集合的擴容,其實是對數組的擴容,minCapacity集合的大小,進行對比判斷是否應該進行擴容,使用了Arrays.copyOf()方法進行擴容,

原文有進行詳細的解釋,這個方法把第一個參數的內容復制到一個新的數組中,數組的大小是第二個參數,并返回一個新的數組,關于oldData的變量上文有詳細的注釋

?
1
2
3
4
5
6
7
8
9
/**
  * 檢查索引是否出界
  * @param index
  */
 private void RangeCheck(int index){
   if(index > size || index < 0){
     throw new IndexOutOfBoundsException("下標超出,Index: " + index + ", Size: " +size);
   }
 }

一個下標的檢索是否出 1 /**

?
1
2
3
4
5
6
7
8
9
10
11
* 添加元素
   * 將指定的元素添加到集合的末尾
   * @param e 添加的元素
   * @return
   */
  public boolean add(E e){
    ensureCapacity(size+1);
    elementData[size]=e;
    size++;
    return true;
  }

添加元素,先進行擴容,在賦值,然后元素加一,注意 size+1 字段size并沒有加一,這里進行的是算術的運算,所以在后面才需要進行自增

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
   * 添加元素
   * 將元素添加到指定的位置
   * @param index 指定的索引下標
   * @param element 元素
   * @return
   */
  public boolean add(int index, E element){
    RangeCheck(index);
    ensureCapacity(size+1);
    // 將 elementData中從Index位置開始、長度為size-index的元素,
    // 拷貝到從下標為index+1位置開始的新的elementData數組中。
    // 即將當前位于該位置的元素以及所有后續元素右移一個位置。
    System.arraycopy(elementData, index, elementData, index+1, size-index);
    elementData[index]=element;
    size++;//元素加一
    return true;
  }

這里不同的是 System.arraycopy(elementData, index, elementData, index+1, size-index);

這是一個c的內部方法,詳細的原文有解釋,這里就不說了,這個也是整個ArrayList的核心所在,也Arrays.copyOf()的內部實現原理

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
   * 添加全部元素
   * 按照指定collection的迭代器所返回的元素順序,將該collection中的所有元素添加到此列表的尾部。
   * @param c
   * @return
   */
  public boolean addAll(Collection < ? extends E>c){
    Object[] newElement=c.toArray();
    int elementLength=newElement.length;
    ensureCapacity(size+elementLength);
    //從newElement 0的下標開始,elementLength個元素,elementData size的下標
    System.arraycopy(newElement, 0, elementData, size, elementLength);
    size+=elementLength;
    return elementLength!=0;
  }

基本上其他方法都只是根據不同的情況進行不同的處理,比如通過接口把數據對象傳遞進來然后獲取長度進行擴容,在把數據使用System,arraycopy復制到新的數組中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
   * 指定位置,添加全部元素
   * @param index 插入位置的下標
   * @param c 插入的元素集合
   * @return
   */
  public boolean addAll(int index, Collection<? extends E> c){
    if(index > size || index < 0){
      throw new IndexOutOfBoundsException("Index: " + index + ", Size: " +size);
    }
    Object[] newElement=c.toArray();
    int elementLength=newElement.length;
    ensureCapacity(size+elementLength);
    int numMoved=size-index;
    //判斷插入的位置是否在數組中間
    if(numMoved>0){
      //把index插入位置的后面的所有元素往后移
      //elementData index下標開始的numMoved個元素插入到elementData 的index+elementLength位置
      System.arraycopy(elementData, index, elementData, index+elementLength, numMoved);
    }
    //把newElement里從0開始的elementLength個元素添加到elementData index開始的位置
    System.arraycopy(newElement, 0, elementData, index, elementLength);
    size += elementLength;
    return elementLength != 0;
  }
  
  /**
   * 指定下標賦值
   * @param index
   * @param element
   * @return
   */
  public E set(int index,E element){
    RangeCheck(index);
    E oldElement=(E)elementData[index];
    elementData[index]=element;
    return oldElement;
  }
  
  /**
   * 根據下標取值
   * @param index
   * @return
   */
  public E get(int index){
    RangeCheck(index);
    return (E)elementData[index];
  }
  
  /**
   * 根據下標移除元素
   * @param index
   */
  public E remove(int index){
    RangeCheck(index);
    E oldElement=(E)elementData[index];
    /** 移除的下標后面的元素數量 */
    int numMoved=size-index-1;
    //如果在數組范圍內就進行移動
    if(numMoved>0)
      System.arraycopy(elementData, index+1, elementData, index, numMoved);
    //移除
    elementData[--size]=null;
    return oldElement;
  }
  
  /**
   * 根據元素移除
   * @param obj
   * @return
   */
  public boolean remove(Object obj){
    //Arraylist允許存放null,所以也要進行判斷處理
    if(obj==null){
      for(int index=0;index<size;index++){
        if(elementData[index]==null){
           remove(index);
           return true;
        }
      }
    }else{
      for(int index=0;index<size;index++){
        if(obj.equals(elementData[index])){
           remove(index);
           return true;
        }
      }
    }
    return false;
  }
  
  /**
   * 根據下標移除指定范圍內的元素
   * @param fromIndex 開始
   * @param toIndex 結束
   */
  protected void removeRange(int fromIndex, int toIndex){
    RangeCheck(fromIndex);
    RangeCheck(toIndex);
    //要移動的元素數
    int numMoved = size - toIndex;
    //把toIndex后面的元素移動到fromIndex
    System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);
    //要移除的元素數量
    int newSize=size-(toIndex-fromIndex);
    while(size!=newSize){
      elementData[--size]=null;
    }
  }
  
  /**
   * 把數組容量調整到實際的容量
   */
  public void trimToSize(){
    int leng=elementData.length;
    if(size<leng){
      Object[] old=elementData;
      elementData=Arrays.copyOf(elementData, size);
    }
  }
  /**
   * 把集合元素轉換成數組
   * @return
   */
  public Object[] toArray(){
    return Arrays.copyOf(elementData, size);
  }
  
  public <T>T[] toArray(T[] a){
    if(a.length<size){
      return (T[]) Arrays.copyOf(elementData,size, a.getClass());
    }
    //把集合元素復制到a數組中
    System.arraycopy(elementData, 0, a, 0, size);
     if (a.length > size){
       for(int index=size;index<a.length;index++){
         a[index] = null;
       }
     }
     return a;
  }

基本上都是對數組進行操作和使用c的方法進行賦值移動等,詳細的可以查看原文,原文中除了那個私有變量外也沒多少問題,代碼可以完美運行,這李要注意的和難點就會是System,arraycopy和Arrayist.copy()這2個方法
和在擴容方法里oldData這個變量的使用,這個變量真的很好,一開始我也不知道為什么要這么使用,在原文的末尾會進行解釋。

以上所述是小編給大家介紹的Java ArrayList 實現實例講解,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的,在此也非常感謝大家對服務器之家網站的支持!

原文鏈接:http://www.cnblogs.com/xiaohuihui96/archive/2016/11/03/6025102.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 夜本色 | 操操日 | 久久久久久久久久久久网站 | 国产成人精品一区二区三区四区 | 精品久久精品 | 欧美在线一区二区 | 亚洲精品一级 | 精品国产欧美一区二区 | 成人欧美亚洲 | 成人精品久久久 | 日韩av一区二区在线观看 | 久久99久久99精品免观看粉嫩 | 久久国产视频精品 | 欧美一区二区三区在线看 | 亚洲综合视频 | 桃色视频在线播放 | www.99精品| 操操操干干干 | 亚洲 精品 综合 精品 自拍 | 成人免费毛片aaaaaa片 | 婷婷久 | 黄色日本视频 | 99热最新| 91精品国产一区二区 | 亚洲综合中文 | 精品日韩一区 | 成人一区二区在线 | 国产成人毛片 | 久久久久国产精品午夜一区 | 午夜视频在线 | 亚洲午夜精品片久久www慈禧 | 精品国产乱码久久久久久久软件 | 国产精品一区在线观看 | 中国黄色三级毛片 | 色综网 | 日本黄色免费大片 | 久久亚洲一区 | 欧美国产精品一区二区三区 | 日本一区二区三区免费观看 | 色视频在线免费观看 | 欧美一级全黄 |