Java:走進類集Collection---List接口篇

目錄

 

Collection

1.出現版本

2.解決問題

3.定義

4.繼承關係

5.常用操作方法

1.List

1.1List接口

1.2ArrayList

1.3LinkedList

1.4Vector

1.5List子類的"炫耀"(各自優勢)


Collection

1.出現版本

JDK1.2

2.解決問題

數組定長問題

3.定義

Collection接口是Java中保存單個對象的最頂層接口

public interface Collection<E> extends Iterable<E> 

繼承了Interable接口

4.繼承關係

 

5.常用操作方法

  • 添加元素:boolean add(E e);

  • 刪除元素:boolean remove(Object o);

  • 查找元素:boolean contains(Object o);

  • 取得集合大小:int size();

  • 轉爲數組:Object[] toArray();

  • 取得類集的迭代器:Iterator<E> iterator();

  • Collection接口中兩個重要方法add()、inerator()在他的子接口中都有這兩個方法

1.List

1.1List接口

List子接口與Collection接口相比最大的特點在於其有一個get()方法,可以根據索引取得內容。由於List本身還是接口,要想取得接口的實例化對象,就必須有子類,在List接口下有三個常用子類:ArrayList、Vector、 LinkedList。

1.1.1獨有方法

index默認從0開始編號

  • 根據索引下標取得元素:E get(int index);

  • 根據索引下標修改元素,返回修改前的數據:E set(int index,E element);

1.1.2常用子類

 

1.2ArrayList

出現版本:JDK1.2

1.2.1基本操作

代碼:

package SaveSingle.RList;
​
import java.util.List;
import java.util.ArrayList;
​
​
public class test {
    public static void main(String[] args){
        // 此時集合裏面只保存String類型
        List<String> list = new ArrayList<>();
        list.add("Hello") ;
        // 重複數據 
        list.add("Hello") ;
        list.add("World") ;
        System.out.println(list) ;
    }
}

結果:

結論:List允許保存重複數據

1.2.2List的get()操作

代碼:

package SaveSingle.RList;
​
import java.util.List;
import java.util.ArrayList;
​
​
public class test {
    public static void main(String[] args){
        // 此時集合裏面只保存String類型
        List<String> list = new ArrayList<>();
        list.add("Hello") ;
        // 重複數據 list.add("Hello") ;
        list.add("World") ;
        for(int i = 0;i < list.size();i++){
            System.out.print(list.get(i)+"、");
        }
    }
}

結果:

結論:list可以通過get(索引)獲得數據元素

1.2.3Collection進行輸出處理

get()方法是List子接口提供的。如果現在操作的是Collection接口,那麼對於此時的數據取出只能夠將集合變爲對象數組操作

代碼:

package SaveSingle.RList;
​
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
​
​
public class test {
    public static void main(String[] args){
        // 此時集合裏面只保存String類型
        List<String> list = new ArrayList<>();
        list.add("Hello") ;
        // 重複數據 
        list.add("Hello");
        list.add("World") ;
        Object[] result = list.toArray();
        System.out.println(Arrays.toString(result));
    }
}

結果:

1.2.4添加自定義類

List集合中添加自定義類

使用contains()、remove()需要equals()的支持

public boolean equals(Object obj){
            if(this == obj){
                return true;
            }
            if(!(obj instanceof Person)){
                return false;
            }
            Person per = (Person) obj;
            return this.age.equals(per.age)&&this.name.equals(per.name);
        }

1.2.5底層數組擴容詳解

源代碼:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
​
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

minCapacity:所需的最小數組容量

oldCapacity:原先的數組容量(擴容前)

newCapacity:新的數組容量(擴容後)

MAX_ARRAY_SIZE:MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8

分析:

  1. 獲取到原先的數組容量;

  1. 新容量= 1.5舊容量;

  2. 如果new < min(新容量 < 當前所需的最小容量),則將當前所需容量賦爲新的數組容量

  3. 如果new > max(新容量 > 數組最大容量),調用hugeCapacity()函數

    1. min < 0(當前所需最小容量 < 0),拋出內存錯誤異常;

    2. min > max(當前所需最小容量 > 數組最大容量),此時將Integer.MAX_VALUE賦爲新的數組容量;否則,將MAX_ARRAY_SIZE賦爲新的數組容量

1.3LinkedList

1.3.1出現版本

JDK1.2

1.3.2基本操作

和ArrayList操作差不多

 

1.4Vector

1.4.1提出版本

JDK1.0

1.4.2基本操作

代碼:

package SaveSingle.RList;
​
import java.util.List;
import java.util.Vector;
​
public class test {
    public static void main(String[] args){
        List<String> list = new Vector<>() ;
        list.add("hello");
        list.add("hello"); 
        list.add("bit");
        System.out.println(list);
        list.remove("hello");
        System.out.println(list);
    }
}

結果:

1.4.3底層數組擴容詳解

源代碼:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
​
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

分析:

注意到,這裏與ArrayList那個擴容操作基本一致,但是有一句不同哦

int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);

簡單來講,一下這個語句吧,其他請看上面ArrayList那塊的部分

  1. capacityIncrement是什麼?

    protected int capacityIncrement;

    這是什麼鬼,繼續找會發現,這個參數可以在實例化對象時自定義

    public Vector(int initialCapacity, int capacityIncrement) {
            super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            this.elementData = new Object[initialCapacity];
            this.capacityIncrement = capacityIncrement;
        }

    摸索許久,這個參數作用大概是:控制數組填滿了之後要怎麼增加,算是一種增加策略吧。

  2. 比如,在實例化對象時,給定capacityIncrement=10(>0),那麼後續newCapacity = oldCapacity+10;如果不給定值或者給一個<0的值,那麼後續newCapacity = 2oldCapacity;

1.5List子類的"炫耀"(各自優勢)

1.5.1ArrayList VS LinkedList

相同點:

  • 出現版本:均出現與JDK1.2時期;

  • 線程安全性:異步處理,線程不安全,效率較高

不同點:

  • ArrayList:基於數組實現,在實例化對象時自定義了數組大小,在內部就會開闢一個自定義大小的數組,存儲元素多導致數組容量不夠時,會進行動態擴容擴充數組的容量。但是,這種擴充並不是無限的(適用於經常查找的情況下)

  • LinkedList:底層採用雙向鏈表實現(不存在擴容操作);

    特殊:是JDK Queue的一個子類(適用於增刪頻繁的情況下)

1.5.2ArrayList VS Vector

  ArrayList Vector
出現版本 JDK1.2 JDK1.0
調用無參構造 懶加載策略,在構造方法階段並不初始化對象數組,第一次添加元素時初始化對象數組大小爲10 產生對象時,內部數組初始化爲10的數組
擴容策略 新數組大小變爲原數組的1.5倍 新數組大小變爲原數組的2倍
線程安全 異步處理,線程不安全效率較高 在方法上加鎖(synchronized同步方法),線程安全,效率較低(鎖的是當前Vector對象,當前對象的所有方法均上鎖,其他線程不可調用)(讀讀互斥)
遍歷 不支持較老的迭代器Enumeration 支持較老迭代器Enumeration
特殊   JDK內置的Stack繼承Vector
  • 調用無參構造

    • ArrayList:

      無參構造賦給底層數組一個空數組;

      public ArrayList() {
              this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
          }

       

    • Vector:

      構造函數時指定底層數組初始化大小爲10;

      public Vector() {
              this(10);
          }

       

  • 擴容策略

    • ArrayList:

      擴容1.5倍;

      int newCapacity = oldCapacity + (oldCapacity >> 1);

       

    • Vector:

      擴容2倍;

      int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                               capacityIncrement : oldCapacity);

       

  • 線程安全

    • ArrayList:

      public boolean add(E e) {
              ensureCapacityInternal(size + 1);  // Increments modCount!!
              elementData[size++] = e;
              return true;
      }

       

    • Vector:

      方法上加鎖;

      public synchronized void addElement(E obj) {
              modCount++;
              ensureCapacityHelper(elementCount + 1);
              elementData[elementCount++] = obj;
          }

       

  • 遍歷

    Vector支持較老迭代器Enumeration,該方法返回一個Enumeration迭代器對象

    public Enumeration<E> elements() {
            return new Enumeration<E>() {
                int count = 0;
    ​
                public boolean hasMoreElements() {
                    return count < elementCount;
                }
    ​
                public E nextElement() {
                    synchronized (Vector.this) {
                        if (count < elementCount) {
                            return elementData(count++);
                        }
                    }
                    throw new NoSuchElementException("Vector Enumeration");
                }
            };
        }

     

  • 特殊

    Stack繼承了Vector,Stack類也是JDK1.0出現的

    class Stack<E> extends Vector<E> {

     

 

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