原文链接.
一、List,Map和Set三者区别:
list(注重顺序): List接⼝存储⼀组不唯⼀(可以有多个元素引⽤相同的对象),有序的对象;
Set(注重独⼀⽆⼆的性质): 不允许重复的集合。不会有多个元素引⽤相同的对象。HashSet可以存一个空值(null),TreeSet不能存空值(null)
Map(⽤Key来搜索的专家): 使⽤键值对存储。 Map会维护与Key有关联的值。两个Key可以引⽤相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。
二、常用集合是否能存储空值(null):
1. List中:ArrayList 和 LinkedList 都可以存储多个空值(null);
2. Map中:
Ⅰ. HashMap,可以存储一个 key 为 null 的的值:
HashMap的put方法:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
这里put时需要计算hash()方法,当key为null时,hash()直接返回0,不会调用key。hashCode()方法。不会产生空指针报错。不过HashMap的key只能存储一个null,因为key是不能重复的,所以有且只能有一个null。
注意: HashMap 允许有一个 Node 的 Key 为 null,该 Node 一定会放在第 0 个桶的位置,因为这个 Key 无法计算 hashCode(),因此只能规定一个桶让它存放。
Ⅱ. TreeMap,不能存 key 为 null 的值
TreeMap的put方法:
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++