Map的key是一個Set,可是Map的value不是一個List,不過能夠將其看作一個List。java
Map的values()方法返回的是map的全部value,可是它不是一個List,而是一個內部類Values數組
HashMap中的特性安全
查看values源代碼:性能
public Collection<V> values() { Collection<V> vs = values; return (vs != null ? vs : (values = new Values())); }
能夠看出,values方法返回的是一個集合:newValues()~!this
該內部類以下:spa
private final class Values extends AbstractCollection<V> { public Iterator<V> iterator() { //返回newValueIterator方法的返回值 return newValueIterator(); } public int size() { //返回外部類實例的size實例變量的返回值 return size; } public boolean contains(Object o) { //返回外部類實例的containsValue(o)的返回值 return containsValue(o); } public void clear() { //調用外部類實例的clear方法 HashMap.this.clear(); } }
這個Values類繼承AbstractCollection,可是它卻不算一個集合類,由於它沒有add方法,即不能夠添加元素,不能存儲任何java對象。它的做用是遍歷Map中全部的value線程
遍歷方法iterator():主要是依賴ValueIterator類:code
查看newValueIterator類:對象
查看nextEntry方法:繼承
在TreeMap中方法是相似的,可是因爲它是經過紅黑樹實現的,因此它遍歷的時候仍是利用的二叉樹的特色:查找子節點。。。。再也不敘述
綜上:
Map的values方法返回的是map的全部value,該value是一個不能存儲元素的Collection的實現類,因此程序遍歷該集合便是遍歷map的全部value
Map和List的實現沒有太大的類似之處,就是用法挺像
List主要有三個實現類:ArrayList,Vector,LinkedList
Vector有一個實現類:Stack,它只比Vector多了5個方法,本質上仍是一個Vector,它們是線程安全的,不過已經再也不推薦使用了,從1.6版本開始,已經被Deque取代,它也有一個實現類ArrayDeque,它既有隊列的性質又有棧的性質
Vector基本已被ArrayList取代,它相比ArrayList,優點是線程安全的,不過,使用ArrayList時,也可使用Collection的靜態方法來將其包裝成線程安全的,故Vector再也不敘述
在ArrayList中有一行
private transient Object[] elementData;
它是用來保存集合的元素的數組,經過transient修飾,保證了序列化時不會直接序列化該數組,而是經過ArrayList提供的writeObject和readObject方法來實現定製序列化。
ArrayList底層採用數組存儲,在數據插入的時候,須要作兩件事:
1:保證ArrayList底冊封裝的數組長度大於集合元素的個數
2:將插入位置以後的全部元素總體向後移動一格
查看源代碼:
public E remove(int index) { //若是index大於等於size,拋出異常 RangeCheck(index); modCount++; //保證index處的元素 E oldValue = (E) elementData[index]; //計算總體搬家的元素個數 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index + 1, elementData, index, numMoved); //釋放被刪除的元素,讓GC回收 elementData[--size] = null; // Let gc do its work return oldValue; }
能夠看出,當向ArrayList添加刪除元素的時候,都須要對數組進行總體搬家,性能較差,可是查找的時候:
直接經過數組取值,性能和數組幾乎同樣好
添加時:
public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); //保證ArrayList的底層數組老是能夠保存全部元素 ensureCapacity(size+1); // Increments modCount!! /*將elementData數組中index後面的全部元素向後移動一格,這樣就能夠將index處的位置空出來*/ System.arraycopy(elementData, index, elementData, index + 1, size - index); //將新元素放置在index處 elementData[index] = element; size++; }
這裏調用了ensureCapacity,源碼以下:
能夠看到ArrayList在超過當前容量時,固定的將新容量擴充至原來的1.5倍
LinkedList本質上是一個雙向鏈表,所以它也是使用內部類Entry來保存數據元素:
private static class Entry<E> { //集合的元素 E element; //指向下一鏈表節點的引用 Entry<E> next; //指向上一鏈表節點的引用 Entry<E> previous; //構造器 Entry(E element, Entry<E> next, Entry<E> previous) { this.element = element; this.next = next; this.previous = previous; } }
能夠看出Entry表明雙向鏈表的一個節點,element是元素自己的值,另外就是鏈表節點的上/下節點的引用,插入數據時形如:
源碼:
主要用到兩個方法:
entry(index)和addBefore();
emrty(index)是get(int index)的底層實現,因爲底層是鏈表,因此LinkedList必須一個元素一個元素的遍歷,直到找到第index個元素
由此能夠看出每次查找元素都須要遍歷鏈表自己,性能較差,不能像ArrayList同樣直接拿到index處的元素
同時看看get(int index)的源碼,就是對entry方法的簡單封裝
public E get(int index){ return entry(index).element; }
再看看單純的插入源碼:
若是隻是單純的插入,LinkedList的性能會很到,可是若是在指定位置插入的話,性能也會受影響,由於它涉及到了查找元素,增長了搜索過程。
刪除也是同理:
先查找,再刪除
具體實現:
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; //將被刪除的兩個元素的引用都置爲空,gc回收 e.next = e.previous = null; e.element = null; size--; modCount++; return result; }
能夠看出首先將被刪除元素保存起來,再將被刪除元素的next賦給它上一節點的next,將其previous賦給它next節點的previous,即將它本身自己從鏈表中剔除了,再把它自己置爲null,最後返回以前保存的被刪除元素
整體來看,ArrayList的性能優於LinkedList,除非常常添加元素時,否則優先考慮ArrayList
Iterator是一個迭代器接口,用於統一的迭代各類Collention集合,至於各集合返回的Iterator實現類,程序不關心,迭代的方式由各集合的實現類本身實現。
使用Iterator迭代是不要刪除集合中的元素,否則會發生ConcurrentModeficationException