关于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; } 本文转自博客园沉睡森林@漂在北京的博客,原文链接:关于Collection接口下相关类接口的问题及分析,如需转载请自行联系原博主。 |