1. 程式人生 > 實用技巧 >Java集合學習筆記(1)

Java集合學習筆記(1)

java集合

1. 集合關係圖

  • 集合介面

terface.png)

  • 實現類

2. LinkedList與ArrayList

2.1常用api,迷惑看https://docs.oracle.com/javase/7/docs/api/

  • 構造

    • ArrayList() 構造一個初始容量為0的空列表,官方文件上說是10, 我認為不正確。原始碼中建構函式中陣列指標指向一了空陣列,儘管size欄位在申明時初始化為10, 但是不代表構造完成後陣列大小為10。當插入元素時才開始擴容為10。

      int[] array = {}; // 等價與int[] array = new int[0]
      // array長度為0,但是不為null
      // null表示這個變數指向的物件為不存在,還沒有給物件分配記憶體空間
      // 此處的array指向了一個物件,只不過這個物件陣列長度為零罷了。
      
    • ArrayList(Collection<? extends E>) 構造一個包含集合的元素,按照他們由集合迭代器返回的順序構建ArrayList。如果集合內的元素Class一樣,也就是說型別一樣,直接指向Collection。如果是子類,利用Arrays.copy()複製,進行型別強轉。
    • ArrayList(int initailCapacity) 構造具有初始容量的ArrayList,一般而言,如果事先知道有多少個元素,最好指定容量,避免不必要的resize()。儘管陣列容量不為0, 但是有效元素個數size為0!!!
    • boolean add(E e) 增加元素到列表末尾

    • boolean add(int index, E element) 在索引index前面插入element。

    List<Integer> array = ArrayList(10);
    array.add(2, 5); 
    // 上面的程式碼出現數組越界異常
    // 我以為聲明瞭10個空間大小,每個初始化為0,所以我可以這麼幹啊。
    // 儘管聲明瞭大小為10的陣列,但是size = 0, size為有效元素的個數。
    // add()是針對下標在0-size-1之間的陣列。
    
    • boolean addAll(Collection<? extends E>) Collectin加到arraylist尾部
    • boolean remove(int index) 刪除index下標,當然了,index也必須時在0-size-1之間

    • boolean remove(Object 0) 刪除第一個元素0,內部使用equals()比較

    // 貼一段我覺得寫得很棒的程式碼
    // 如果我實現下面的邏輯,肯定是return到處扔,肯定要把break換成fastRemove(es, i)和return true
    // 要是需求變了,要求remove失敗返回true, 那就拉胯了。
    public boolean remove(Object o) {
            final Object[] es = elementData;
            final int size = this.size;
            int i = 0;
            found: {
                if (o == null) {
                    for (; i < size; i++)
                        if (es[i] == null)
                            break found;//跳出found
                } else {
                    for (; i < size; i++)
                        if (o.equals(es[i]))
                            break found;//跳出found
                }
                return false;
            }
            fastRemove(es, i);
            return true;
        }
    
    • E set(int index, E element) 返回原來的值
    • E get(int index)
  • 其他

    • int size() 有效元素個數
    • int indexOf(Object o) 返回元素下標, 內部使用equals比較大小
    • Iterator iterator() 返回迭代器
    • Object clone()返回淺拷貝arrayList()
    • contains(Object o) 內部使用equeals()
    • Object[] toArray() 返回對應的陣列

LinkedList, 除了ArrayList的一些操作,還可以當棧,佇列,雙端佇列,所以api要多一點

  • 建構函式

    • LinkList()
    • LinkList(Collection<? extend E> c)
    • boolean addFirst(E e) boolean addLast(E e) 雙端佇列常用操作

    • add(E e) 隊尾部加

    • E remove() 刪除第一個節點

    • E removeFirst()

    • E removeLast()

    • E poll() 刪除第一個節點

    • E pollFirst()

    • E pollLast()

    • set(in index)
  • 檢視

    • E peek() 獲得第一個元素

    • E peekFirst() 獲得第一個元素

    • E peekLast() 獲得最後一個元素

    • E getFirst()

    • E getLast()

2.2 內部實現分

  • ArrayList : 可擴容的動態陣列

    • 執行緒不同步。
    • 預設初始容量為 10,當陣列大小不足時容量擴大為 1.5 倍。
    • 為追求效率,ArrayList 沒有實現同步(synchronized),如果需要多個執行緒併發訪問,使用者可以手動同步,也可使用 Vector 替代。
  • LinkedList: 雙向連結串列

  • 執行緒不同步。

  • 雙向連結實現。LinkedList 同時實現了 List 介面和 Deque 介面,也就是說它既可以看作一個順序容器,又可以看作一個佇列(Queue),同時又可以看作一個棧(Stack)。

  • 當你需要使用棧或者佇列時,可以考慮使用 LinkedList,一方面是因為 Java 官方已經宣告不建議使用 Stack 類,更遺憾的是,Java 里根本沒有一個叫做 Queue 的類(它是個介面名字)。關於棧或佇列,現在的首選是 ArrayDeque,它有著比 LinkedList(當作棧或佇列使用時)有著更好的效能

  • Vector:實現同步的可擴容動態陣列

    • 執行緒同步。它的同步是通過 Iterator 方法加 synchronized 實現的。

    • 預設初始容量為 10,當陣列大小不足時容量擴大為 2 倍。

2.3 區別與聯絡

  • ArrayList底層是陣列,可以通過下標直接定位到某個元素,時間複雜度為O(1),所以ArrayList更擅長read。當write的時候,如果是陣列中間插入或者刪除某個元素,那麼則需要移動大量的元素。當我們只是read資料,或者是在末尾插入或者刪除資料時,建議用ArrayList
  • LinkedList底層是雙向連結串列,當我們需要read某個元素時,可以從頭或者從尾部開始遍歷,具體取決於離頭部近還是離尾部近。當需要wirte資料時,只用移動指標。所以,LinkedList更適合儲存那些常常被修改的資料。