java.util包提供了兩種java
ArrayList LinkedList
ArrayList比LinkedList經常使用不少,緣由是:
ArrayList查找更容易算法
ArrayList封裝了一個數組Object[]數組
數組的初始化緩存
ArrayList array = new ArrayList();
封裝一個空數組, {}安全
ArrayList array = new ArrayList(10);
封裝一個大小爲10的數組 new Object[10];
性能優化
數組如何實現擴容
數據結構
ArrayList.add/addAll都須要先進行擴容檢查,
相似,併發
對象調用方法,要進行對象判空, UI操做以前要進行,線程檢查
擴容檢查: size+增長的大小 與 數組.length 比較
計算數組擴容的數組長度:性能
首先,擴容至原數組大小的一倍,size+增長的大 小與其比較:
若是大於,擴容至原數組大小的一倍
若是小於,擴容至size+增長的大小;優化
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); }
擴容使用的是: Array.copyof(array, newLen)
removeAll如何實現
與remove()不一樣,remove使用System.copy完成數組的 部分移動
而removeAll,使用的算法:
ArrayList array1 = new ArrayList(); array1.addAll({0,3,5,7,3,6}); int[] array2 = {3,5,4}; array1.removeAll(array2);
首先,遍歷array1中每一個元素,若元素 不在array2內,將計數位置的值設置爲元素的值並將計 數+1;
遍歷完成後,計數爲數組剩餘元素的個 數,將計數以後的元素清空.
算法詳細:
  0,3,5,7,3,6 ;<br>   遍歷以後,計數爲2,數組爲0,7,6,7,3,6;<br>   清空以後,0,7,6,null,null,null;
Node的數據結構
Node<E> { E element; Node<E> prev; Node<E> next; }
基本結構
Node<E> first, last
Linked是雙向鏈表,first,last指向表頭,表尾
java.util包提供了兩種Map:
1.HashMap
2.TreeMap
Android爲了性能優化,提供了HashMap的替代品:
1.ArrayMap
2.SparseMap
它倆能夠在數據量都在千級之內的狀況下,
若是key的類型爲int,使用SparseMap,
若是key的類型爲其它類型,使用ArrayMap
HashMap相比TreeMap更經常使用
數據結構
Node的數據結構:
Node<K,V> { int hash; K key; V value; Node<K,V> next; }
基本數據結構:
Node<K,V>[] table; float loadFoctor;//默認值0.75f int threshold;
能夠看出HashMap的數據結構是數組+鏈表
擴容
何時擴容
當調用put/putAll時,實際上都是調用putVal方法
先建立Node,再查看新的Node放入數組,仍是鏈表;
當++size>threshold,則須要擴容
table如何擴容
它的擴容包含兩個步驟:
1. 肯定擴容的大小; 2. 如何移動元素,包含數組中的元素與鏈表中的元素;<br>
肯定擴容的大小:
threshold默認值 = 16*0.75f=12
每次擴容,
先建立一個threadhold大小的數組,賦給tble,也就是擴容至threadhold
再,threadhold = threadhold <<1,擴大一倍
如何移動元素,包含數組中的元素與鏈表中的元素:
1.若是元素只在數組裏,而沒有鏈表:
新的位置是 e.hash&(newCap-1)
2.元素在鏈表上:
根據(e.hash & oldCap) == 0 決定是在原位置仍是在原位置+oldCap上
鏈表可能會分爲兩部分
數據結構
TreeMapEntry的數據結構
TreeMapEntry<K, V> { K key; V value; TreeMapEntry<K, V> left; TreeMapEntry<K, V> right; TreeMapEntry<K, V> parent; }
TreeMap的數據結構:
TreeMapEntry<K, V> root; Comparator<? super K> comparator;
數據結構
int[] mKeys; Object[] mValues;
Vector
HashTable
用於讀寫分離,實現讀併發,寫同步
併發的不一樣策略:
1.Blocking容器
2.CopyOnWrite容器
3.Concurrent容器
用於解決限制容量的容器的存取問題
相似生產者-消費者
容器爲空時,阻塞取線程
容器滿時,阻塞存線程
寫時賦值,即添加元素時,先複製整個容器,添加到複製的容器中,
再將容器引用指向複製的容器,達到讀的最大併發;
適用於讀多寫少的狀況;
使用分段鎖,首先將容器分紅多段,每段使用不一樣的鎖,對不一樣段達到讀寫併發,相同段讀併發,寫同步