關于Collection接口下相關類接口的問題及分析
*List和*Set的異同
List和Set本身都是接口,他們都繼承了Collection接口,分別表示2種數據機構。一種*List可以有重復的數據,可以有多個NULL值;而另外一種*Set不能有重復數據,最多只能有一個NULL值。在他們的源代碼上可以很清楚的發現這些差異。
可以打開ArrayList的add方法代碼如下:
public boolean
add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++]
= e; return true; } |
而HashSet的add方法代碼如下:
public boolean add(E e) { return map.put(e, PRESENT)==null; } |
一個是數組實現,一個使用Map實現,并且HashSet的元素作為map的key值,必然不能重復。
關于ArrayList和Vector的異同
ArrayList不是線程安全的,而Vector是的。具體可以看Vector的add方法和insertElementAt方法的代碼:
public void add(int index, E element) { insertElementAt(element, index); } public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new
ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } |
代碼里面有大家熟悉的synchronized關鍵字,說明進行了線程同步。而ArrayList中的add方法沒有進行同步,自然不是線程安全的。如果需要使用ArrayList且需要同步可以使用如下代碼:
List list = Collections.synchronizedList(new ArrayList()); |
ArrayList,Vector, LinkedList的存儲性能和特性
ArrayList和Vector都是使用數組方式存儲數據,此數組元素數大于實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector由于使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。
關于Collections和Collection的區別
Collection是集合類的上級接口,繼承與他的接口主要有Set 和List。Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。
關于HashMap和HashTable的異同
都是實現了Map接口,利用key和value對應存取對象,都是基于Hash算法實現快速存取。但是HashTable是線程安全的,HashMap不是,在效率上因為同步的原因有所差異。并且,HashMap中的key可以有NULL但最多一個,而HashTable不能有NULL的key值。
HashMap的put方法代碼如下:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = 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); return null; } |
而HashTable的put方法代碼如下:
public synchronized
V put(K key, V value) { // Make sure the value is not null if (value == null) { throw new NullPointerException(); } // Makes sure the key is not
already in the hashtable. Entry tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { V old = e.value; e.value = value; return old; } } modCount++; if (count
>= threshold)
{ // Rehash the table if the threshold is exceeded rehash(); tab = table; index = (hash & 0x7FFFFFFF) %
tab.length; } // Creates the new entry. Entry<K,V> e = tab[index]; tab[index] = new Entry<K,V>(hash, key, value, e); count++; return null; } |