DataContainer-數據容器

概念

一、Collection<E>				集合			Object數組
			AbstractCollection
			List<E>				索引訪問
			Set<E>				唯一存儲
二、Map<K,V>					鍵值映射		
			CouncurrentMap<K,V>
			SortedMap<K,V>
三、Comparable<T>

Array	
List<E>	序列				元素可重、存儲有序、N個Null、順序索引
		ArrayList		數組列表		線性表-非同步			查詢-索引訪問-非同步
		LinkedList		鏈接列表		雙向鏈表				插入、刪除-任意位置
		Vector			向量列表		線性表-同步				查詢-索引訪問-同步
Set<E>	集合				元素無重、存儲無序、1個Null
		HashSet			無序			HashMap			
		TreeSet			有序
		SortedSet		可選排序		
		LinkedHashSet	HashTable+LinkedList 	
Map<K,V>		
		HashTable
		HashMap			HashTable
		TreeMap
		SortedMap	
		LinkedHashSet	HashTable+LinkedList

​​ 在這裏插入圖片描述

Collection-集合

Collection<E>-集合接口
CollectionS	 -集合類			差集、並集、拷貝、排序


類型			數據結構			Null值				線程安全		擴容			適用					弱勢
Array		定長數組		
ArrayList	可變數組			N					非安全		1.5+1		查改					增刪插[數組拷貝]	
LinkedList	雙向鏈表			N					非安全		XXX			增刪插[前後引用]		查改
			Deque接口,add,poll提供FIFO隊列操作、堆棧操作、雙端隊列操作
Vector		XXXX			X					安全
HashMap		數組+單向鏈表		Key:Value = 1:N		非安全		2
HashTable	數組+單向鏈表		不允許				安全			2
TreeMap		自平衡紅黑樹		不允許				非安全		
			按鍵排序迭代
HashSet		哈希集合			1					非安全		
			不保證迭代順序
TreeSet		樹集合			1	
			自動排序[自然排序、定製排序]
LinkedHashSet
			特殊順序迭代

List

數據容器		Object數組
			ArrayList		LinkedList		Vector
線程安全		非安全			XXX				安全
數據結構
適用場景		遍歷				插入刪除

ArrayList

//替代元素    返回元素
public E set(int index,E element){
    RangeCheck(index);    //合法性檢查:索引範圍
    E oldValue = (E) elementData[index];    //
    elementData[] = element;
    return oldValue;
}

//添加元素    返回結果
public boolean add(E e){
    ensureCapacity(size+1);    //長度+1、確保容量
    elementData[size++]=e;     //添加
    return true;
}

//插入元素    指定位置
public void add(int index,E element){
    if(index>size||index<0)    //合法性檢查:長度範圍
    throw new IndexOutOfBoundsException("Index:"+index+",Size"+size);
    ensureCapacity(size+1);    //長度+1、確保容量
    System.arraycopy(elementData,index,elementData,index+1,size-index);
                               //數組拷貝,整體移動[向後]
    elementData[index] = element;//設定插入
    size++;
}

//刪除元素    指定位置
public E remove(int index){
    RangeCheck(index);        //合法性檢查:索引範圍
    modCount++;               //修改次數
    E oldValue = (E) elementData[index];
    int numMoved = size-index-1;
    if(numMoved>0)            //數組拷貝,整體移動[向前]
    System.arraycopu(elementData,index+1,index+1,elementData,inde,numMoved);
    elementData[--size] = null;//設定尾部null
    return oldValue;    //返回舊元素
}

//擴容1.5+1    
public void ensureCapaity(int minCapacity){
    modCount++;
    int oldCapacity = elementData.length;    //容量
    if(minCapacity>oldCapacity){
        int newCapacity = (oldCapacity*3)/2+1;
        if(newCapacity < minCapacity)
        newCapacity = minCapacity;
        elementData = Arrays.copyOf(elementData,newCapacity);
                                            //拷貝原有元素
    }
}    

LinkedList

在這裏插入圖片描述

雙端隊列   previous—Entry—next

private transient Entry<E> header = new Entry<>();
private static class Entry<E>{
    E element;
    Entry<E> next;
    Entry<E> previous;
}
//構造方法    目標對象paramE放置在paramEntry1之前,paramEntry2之後
Entry(E paramE,Entry<E> paramEntry1,Entry<E> paramEntry2){
    this.element = paramE;
    this.next = paramEntry1;
    this.previous = paramEntry2;
}

//查詢
private Entry<E> entry(int paramInt){
    if((paramInt<0)||(paramInt>=this.size)){    //合法檢查:範圍檢查
        throw new IndexOutOfBoundsException("Index:"+paramInt+",Size:"+this.zize);      }
    Entry localEntry = this.header;             //查找:從頭部開始————>雙向環                                             
    int i;                                      //最多遍歷size/2個元素
    if(paramInt<this.size>>1){                  //判斷位置?中間位置
        for(i=0;i<=paramInt;i++)                //頭部:向後查找
            localEntry = localEntry.next;
    } else {
        for(i=this.size;i>paramInt;i++)         //尾部:向前查找
            localEntry = localEntry.previous;
    }
    return localEntry;
}

/*插入   
*添加元素:paramE
*目標對象:paramEntry
*/
private Entry<E> addBefore(E paramE,Entry<E> paramEntry){
    //實例化新節點    設置前節點、後節點
    //兩點確定一條直線
    Entry localEntry = new Entry(paramE,paramEntry,paramEntry.previous);
    localEntry.previous.next = localEntry;    //前節點
    localEntry.next.previous = localEntry;    //後節點
    this.size += 1;
    this.moCount += 1;
    return localEntry;
}

//添加    根據位置
public void add(int index,E element){
    addBefore(element,(index==size?header:entry(index)));
}
//隊首添加
public void addFirst(E paramE){    addBefore(paramE,this.header.next);}
//隊尾添加
public void addLast(E paramE){    addBefore(paramE,this.header);}

//刪除
private E remove(Entry<E> e){
    if(e == header)
        throw new NoSuchElementException();
    E result = e.element;              //保留刪除
    e.previous.next = e.next;          //重新引用    前後節點    前後關聯
    e.next.previous = e.previous;
    e.next = e.previous = null;        //解除引用    刪除節點    前後設爲null
    size--;
    modCount++;
    return result
}

public E remove(){
    return removeFirst();
}
//刪除
public E remove(int index){    return remove(entry(index));}
//刪除隊首
public E removeFirst(){    return remove(header.next);}
//刪除隊尾
public E removeLast(){    return remove(header.previous);}

Set

數據結構		Map

HashSet

//底層使用HashMap保存HashSet元素
private transient HashMap<E,Object> map;

//定義虛擬的Object對象:HashMap的Value
private static final Object PRESENT = NEW Object();

//添加    藉助HashMap的add方法
//HashMap的add方法,返回key之前的value值
//如果爲null則說明之前尚未添加key,即HashSet可以添加該元素
public boolean add(E e){
    return map.put(e,PRESENT) == null;
}

//查找    藉助HashMap的contain方法
public boolean contain(Object o){
    return map.containsKey(o);
}

TreeSet

遍歷方式		自然順序、中序遍歷
數據結構		紅黑樹

LinkedHashSet

遍歷方式		自然順序、中序遍歷
數據結構		鏈表

Map

存儲數據		Entry數組
存儲原理		位置(數組下標)由key的哈希值與數組長度計算而來。
			如果數組當前下標已有值,則將數組當前下標的值指向新添加的Entry對象。
哈希碰撞			
			
			Hashtable		HashMap			TreeMap			LinkedHashMap		ConcurrentHashMap
默認容量		11				16
容量要求		無				2的整數次冪
擴容方式		*2+1			*2
數據結構		XXXX			XXXX			紅黑樹				雙向鏈表
順序特性		無序				無序				有序
線程安全		安全				不安全
多線程情況	V慢				V快				XXX				V中
Hash運算		位置索引取模		長度取模
Null值		K:V=1:N			K:V=0:0			K:V=0:0
迭代器		Enumeration		Iterator
方法			contain()		containKey()
							containValue()
適用場景	

ConcurrentHashMap
鎖分段技術		
			[1]首先將Map存放的數據分成一段一段的存儲方式,
			[2]然後給每一段數據分配一把鎖,
			[3]當一個線程佔用鎖訪問其中一個段的數據時,其他段的數據也能被其他線程訪問。

樹化		JDK1.8

TreeMap

1.數據結構	自平衡紅黑二叉查找樹
				Entry節點、Key鍵、Value值、Left左孩子、Right右孩子、Parent父節點、Color顏色

2.排序		comparator比較	Entry的Key節點
3.優點		空間利用率高、性能穩定(O logn)
4.特性		數據大小		左節點<自節點<右節點
排序方式	[1]自然排序		默認升序
		[2]定製排序		可自定義

HashMap

==				數值大小
equals()		數據內容
hashCode()		編碼地址


//數據結構
transient Entry[] table;

static class Entry<K,V> implements Map.Entry<K,V>{
    final K key;
    V value;
    Entry<K,V> next;
    final int hash;
    ...
}

//一、存入
public V put(K key,V value){
    if(key == null)                     // null鍵視爲相同的鍵
        return putForNullKey(value);        //根據key的keycode重新計算hash值
    int hash = hash(key.hashCode());        //搜索指定hash值在對應table中的索引
    int i = indexFor(hash,table.length);            
    //如果i索引出的Entry不爲null,循環遍歷,下一個元素
    for(Entry<>=table[i]; e!=null; e=e.next){       //數組
        Object k;                    
                                                    //鏈表        
        if(e.hash == hash
            && ((k=e.key)==key||key.equals(k))){
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    modCount++;
    addEntry(hash,key,value,i);                     //鏈表Entry    插入
}
//1.插入數組
//hash函數,加入高位計算,防止低位不變,高位變化時,造成hash衝突
static int hash(int h){
    h ^=(h>>>20)^(h>>>12);
    return h^(h>>>7)^(h>>>4);
}

//2.插入鏈表
void addEntry(int hash,K key,V value,int bucketIndex){
    Entry<K,V> e = table[bucketIndex];                     //獲取Entry  bucketIndex索引
    table[bucketIndex] = new Entry<K,V>(hash,key,value,e); //
    if(size==>threshold)                        //判斷容量  Map中的key-value
    resize(2*table.length);                        
}

//查詢    根據hash值查找對應的table位置
static int indexFor(int h,int length){
    return h & (length-1);
}

//二、取出  get
public V get(Object key){
    if(key == null)                    //合法檢查:null
        return getForNullKey();
    int hash = hash(key.hashCode());
    for(Entry<K,V> e = table[indexFor(hash,table.length)];
        e! = null;
        e = e.next){
        Object k;
        if(e.hash == hash &&
            ((k = e.key) ==key || key.equals(k)))
        return e.value;
    }
    return null;
}

LinkedHashMap

//添加    addEntry
void addEntry(int hash,K key,V value,int bucketIndex){
    //調用create方法,將新元素以雙向鏈表的形式加入到映射中

    createEntry(hash,key,value,bucketIndex);
    Entry<K,V> eldest = header.after;
    if(removeEldestEntry(eldest)){           //隊首    正向添加         
        removeEntryForKey(eldest.key);
    } else{        
        if(size >= threshold)                //隊尾    逆向添加
            resize(2*table.length);
    }    
}

//創建節點對象
void createEntry(int hash,K key,V value,int bucketIndex){
    HashMap.Entry<K,V> old = table[bucketIndex];
    Entry<K,V> e = new Entry<K,V>();
    table[bucketIndex] = e;
    //調用元素的addBefore方法,將元素加入到雙向鏈接列表
    e.addBefore(header);    
    size++;
}

//二、獲取    get
public V get(Object key){
                                    //調用父類HashMap的getEntry()方法
    Entry<K,V> e = (Entry<K,V>) getEntry();
    if(e == null)
        return null;
    e.recordAccess(this);                    //記錄訪問殊勳
    return e.value
}

void recordAccess(HashMap<K,V> m){
    LinkedHashMap<K,V> Im = (LinkedHashMap<>K,V) m;
    //如果定義了LinkedHashMap的迭代順序爲訪問順序
    //則刪除以前位置上的元素,並將最新訪問的元素添加到鏈表表頭
    if(Im.accessOrder){
        Im.modCount++;
        remove();
        addBefore(Im.header);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章