这里先说说HashSet。
- HashSet内部也是使用的HashMap来存储
在去重的时候使用很方便
// 得到列表
List<String> list = getList();
// 去重
HashSet h = new HashSet(list);
list.clear();
list.addAll(h);//最后得到的就是没有重复数据的list
HashMap和HashTable
- HashMap和HashTable几乎等价
- HashMap效率高,因为它不是线程安全的,而HashTable是线程安全的。
- HashMap可以存储null的key值,HashTable不行
- 迭代算法不同HashMap是使用fail-fast,所以在有其他线程更改了结构会抛出异常。
- HashTable是线程安全的,所以在单线程操作中效率比HashMap慢,所以那种情况下,使用HashMap更好
- HashMap不能保证元素次序是一直不变的(在添加过程中,超过容积,会像Arraylist那样增加到原有的两倍,然后会倒序的方式装进去,顺序就改变了)
我们主要关注两个的get 和put 方法。
- HashMap
@Override public V put(K key, V value) {
if (key == null) {//这就看到可以key为null
return putValueForNullKey(value);
}
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
if (e.hash == hash && key.equals(e.key)) {//该key已存在则更新值
preModify(e);
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
// No entry for (non-null) key is present; create one
modCount++;
if (size++ > threshold) {//检测大小是否超出容量
tab = doubleCapacity();//重新修改
index = hash & (tab.length - 1);
}
addNewEntry(key, value, hash, index);//新添加
return null;
}
public V get(Object key) {
if (key == null) {//如果key为null,在存null中找
HashMapEntry<K, V> e = entryForNullKey;
return e == null ? null : e.value;
}
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
e != null; e = e.next) {//链表方式,一个一个往下找
K eKey = e.key;
if (eKey == key || (e.hash == hash && key.equals(eKey))) {//如果当前缓存区的key和传入key相同,那么就直接取值。或者hash相同的时候,则比较key值
return e.value;
}
}
return null;
}
- HashTable
public synchronized V put(K key, V value) {
if (key == null) {//这里就能看出hashtable是不允许存空的key和value的
throw new NullPointerException("key == null");
} else if (value == null) {
throw new NullPointerException("value == null");
}
//后面和HashMap没太大区别,所以省略
}
public synchronized V get(Object key) {
//get也是和HashMap查不多的。
}
可以很明显的看到,HashTable的put和get方法都加入了synchronized,保证同一时间只能有个线程来操作,所以在单线程的时候,HashTable也确实效率要低一点。
关于HashMap也可以使用这种方式来同步:Collections.synchronizedMap(hashMap);