关于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;
}
|