1、數組與集合java
數組(能夠存儲對象包括基本類型)是一種常見的數據結構,對元素訪問快速,但長度固定,存儲數據類型需一致。數組
集合只能存儲對象,長度可變,能夠存儲不一樣類型的對象。安全
數組與集合之間能夠經過toArray()和Arrays.asList()相互轉換。注:(asList返回的對象是一個Arrays內部類,並無實現集合的add/remove/clear方法。)數據結構
2、集合框架圖併發
集合類存放在java.util包中,主要兩種類型:Collection和Map,繼承關係以下圖:app
List、Set和Map是集合中的三個主要接口。其中,List和Set繼承自Collection(沒有直接實現類)根接口,Map和Collection相互獨立,但也屬於集合類。
框架
List:有序且容許元素重複;基於數組的Vector和ArrayList適合查詢,而基於鏈表的LinkedList適合添加,刪除操做。異步
Set:無序且不容許元素重複;不能重複的緣由是:Set實現的基礎是Map(HashMap),HashMap的key不能重複。this
Map:鍵值對集合,鍵不能重複,值可重複。spa
3、集合類遍歷
一、Collection
Collection沒有get()方法來獲取某個元素,只能經過iterator()遍歷元素;foreach內部也是採用了Iterator的方式實現(循環體remove/add會致使expectedModCount和modCount不相等報異常);List能夠經過get()方法獲取元素,ListIterator是Iterator的子接口,專門用於List。
//iterator Iterator iterator = list.iterator(); while(iterator.hasNext()){ int i = (Integer) iterator.next(); System.out.println(i); } //foreach for (Object object : list) { System.out.println(object); } //for for (int i = 0 ;i<list.size();i++) { int v= (Integer) list.get(i); System.out.println(v); }
二、Map
1)經過Map.keySet()將Map中的全部key存入到Set集合中,而後經過iterator()獲取迭代器或者foreach遍歷key,最後經過Map.get(key)方法取得對應的值。
//iterator Iterator it=map.keySet().iterator(); while(it.hasNext()){ String key; String value; key=it.next().toString(); value=map.get(key); System.out.println(key+"--"+value); } //foreach for (String key : map.keySet()) {
System.out.println("key= " + key + " and value= " + map.get(key));
}
2)經過Map.entrySet()將鍵值對做爲一個總體一對一對地存放到Set集合中,Map.Entry表示映射關係,而後經過iterator()獲取迭代器或者foreach遍歷獲取鍵(e.getKey())和值(e.getValue());
//iterator Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, String> entry = it.next(); System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); } //foreach for (Map.Entry<Integer, String> entry : map.entrySet()) { System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); }
3)經過Map.values()遍歷全部的value,但不能遍歷key。
for (String v : map.values()) { System.out.println("value= " + v); }
4、接口實現類的區別比較
一、ArrayList和Vector
1)同步性:Vector使用了synchronized方法,是同步和線程安全的,ArrayList是異步和線程非安全的,能夠經過List Collections.synchronizedList(List list)實現同步。
2)數據增加:當元素個數超過容量時,Vector默認增加爲原來的2倍,ArrayList爲1.5倍;ArrayList與Vector均可以設置初始的空間大小,Vector還能夠設置增加的空間大小,而ArrayList沒有提供設置增加空間的方法。
二、ArrayList和LinkedList
1)實現基礎:ArrayList基於數組,LinkedList基於雙向鏈表。
2)效率:get和set操做,ArrayList佔優;add和remove操做LinkedList佔優。
三、HashMap和Hashtable
1)繼承:HashMap繼承於AbstractMap,Hashtable繼承於Dictionary。
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
2)同步性:Hashtable是同步的;HashMap是非同步的,能夠經過Map Collections.synchronizedMap(Map m)實現;如需線程安全,推薦使用ConcurrentHashMap。
3)鍵值要求:HashMap容許存在一個爲null的key,多個爲null的value ;Hashtable的key和value都不容許爲null。
4)遍歷方式內部實現:Hashtable、HashMap都使用了 Iterator;因爲歷史緣由,Hashtable還使用了Enumeration的方式 。
5)默認大小和擴容方式:Hashtable中hash數組默認大小是11,增長的方式是 old*2+1。HashMap中hash數組的默認大小是16,並且必定是2的指數。
jdk1.7 java.util.HashTable // 哈希表默認初始大小爲11 public Hashtable() { this(11, 0.75f); } protected void rehash() { int oldCapacity = table.length; Entry<K,V>[] oldMap = table; // 每次擴容爲原來的2n+1 int newCapacity = (oldCapacity << 1) + 1; // ... } java.util.HashMap // 哈希表默認初始大小爲2^4=16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 void addEntry(int hash, K key, V value, int bucketIndex) { // 每次擴充爲原來的2n if ((size >= threshold) && (null != table[bucketIndex])) { resize(2 * table.length); }
6)Hashtable直接使用對象的hashCode,而HashMap從新計算hash值
jdk1.7
java.util.HashTable // hash 不能超過Integer.MAX_VALUE 因此要取其最小的31個bit int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; // 直接計算key.hashCode() private int hash(Object k) { // hashSeed will be zero if alternative hashing is disabled. return hashSeed ^ k.hashCode(); } java.util.HashMap int hash = hash(key); int i = indexFor(hash, table.length); // 在計算了key.hashCode()以後,作了一些位運算來減小哈希衝突 final int hash(Object k) { int h = hashSeed; if (0 != h && k instanceof String) { return sun.misc.Hashing.stringHash32((String) k); } h ^= k.hashCode(); // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } // 取模再也不須要作除法 static int indexFor(int h, int length) { // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2"; return h & (length-1); }
JDK7中HashMap採用的是位桶+鏈表的方式,即咱們常說的散列鏈表的方式,而JDK8中採用的是位桶+鏈表/紅黑樹(有關紅黑樹請查看紅黑樹)的方式。當某個位桶的鏈表的長度達到某個閥值(8)的時候,這個鏈表就將轉換成紅黑樹,改進鏈表過長查詢慢的問題。另外,JDK8將鏈表頭插改成尾插,避免併發死循環問題,固然仍然是非線程安全,好比數據丟失。
7)Hashtable有一個contains(Object value),功能和containsValue(Object value)功能同樣。