前言1. HashTable2. HashMap3. HashSet4. Vector5. ArrayList6. linkedList7. linkedHashMap8. ConcurrentHashMap9. ConcurrentSkipListSet10. ConcurrentlinkedDeque和ConcurrentlinkedQueue11. CopyOnWriteArrayList和CopyOnWriteArraySet12. linkedBlockingDeque、linkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue总结
前言面试、考试经常问的一个问题:xx集合是否可以添加null值?看到这个问题,总是拿不准,本篇就来总结下,常用数据集合是否可以添加null值(或key为null)。
1. HashTableHashTable不允许null作为key或者value,如果任意一个为null的话,会抛出NullPointerException.
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;
@SuppressWarnings("unchecked")
Entry entry = (Entry)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
上面是HashTable的源码,如果value为空,会在参数检查时抛出空指针异常;如果key为空,则在调用key.hashCode()的时候发生空指针异常。
2. HashMapHashMap允许key或者value为null,当key为null时,null可以作为正常的key,可以通过hashMap.get(null)来获取值;null也可以作为value添加,均可以正常使用。
@Test
public void addNullTest() {
Map hashMap = new HashMap<>();
hashMap.put(null, null);
hashMap.put(null, "Hello");
hashMap.put("Hello", null);
System.out.println(hashMap.get(null));
System.out.println(hashMap.get("Hello"));
}
上述的代码输出结果为:
Hello null3. HashSet
HashSet内部使用了HashMap实现,所以HashSet可以添加null值。验证代码如下:
@Test
public void addNullTest() {
Set hashSet = new HashSet<>();
hashSet.add(null);
hashSet.add(null);
System.out.println(hashSet.contains(null));
}
输出结果为:
true4. Vector
Vector内部维护了一个数组,是可以添加null作为值的,验证代码如下:
@Test
public void addNullTest() {
Vector vector = new Vector<>();
vector.add(null);
vector.add(null);
vector.add(null);
System.out.println(vector.contains(null));
}
输出结果为:
3 true5. ArrayList
ArrayList可以添加null为值,验证代码如下:
@Test
public void addNullTest() {
List arrayList = new ArrayList<>();
arrayList.add(null);
arrayList.add(null);
arrayList.add(null);
System.out.println(arrayList.size());
System.out.println(arrayList.contains(null));
}
输出结果为;
3 true6. linkedList
linkedList允许添加null作为值,验证代码和ArrayList形式一致,不贴验证代码了。
7. linkedHashMaplinkedHashMap允许key或者value为null,或者两者同时为null,当key为null的时候,其hashCode为0,也可以正常当作key值。下面是验证代码:
@Test
public void addNullTest() {
linkedHashMap linkedHashMap = new linkedHashMap<>();
linkedHashMap.put(null, null);
linkedHashMap.put(null, "Hello");
linkedHashMap.put("Hello", null);
System.out.println(linkedHashMap.get(null));
System.out.println(linkedHashMap.get("Hello"));
}
输出结果为:
Hello null8. ConcurrentHashMap
ConcurrentHashMap不允许key或者value为null,会在运行时抛出NullPointerException。以下截取的ConcurrentHashMap的部分源码:
public V put(K key, V value) {
return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
// code fragment...
}
可以看到,putVal里面的参数检查,如果任意一项为空,则会抛出空指针异常。
9. ConcurrentSkipListSetConcurrentSkipListSet不允许添加null作为值,原因和ConcurrentHashMap类似,添加元素时会对参数进行检查,如果为null会抛出空指针异常。
10. ConcurrentlinkedDeque和ConcurrentlinkedQueue两者都不允许添加null值,因为在添加值时都会检查添加进来的值是否为null,如果为null会抛出NullPointerException.
11. CopyOnWriteArrayList和CopyonWriteArraySet这两种数据结构均允许null值的添加。验证代码:
@Test
public void addNullTest() {
CopyOnWriteArrayList copyonWriteArrayList = new CopyOnWriteArrayList<>();
copyOnWriteArrayList.add(null);
copyOnWriteArrayList.add(null);
System.out.println(copyOnWriteArrayList.size());
System.out.println(copyOnWriteArrayList.contains(null));
CopyOnWriteArraySet copyonWriteArraySet = new CopyOnWriteArraySet<>();
copyOnWriteArraySet.add(null);
copyOnWriteArraySet.add(null);
System.out.println(copyOnWriteArraySet.size());
System.out.println(copyOnWriteArraySet.contains(null));
}
输出结果为:
2 true 1 true12. linkedBlockingDeque、linkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue
这几个都不支持null作为值,入参有参数检查,null会抛出NullPointerException。
总结支持添加null的集合有:
HashMapHashSetVectorArrayListlinkedListlinkedHashMapCopyOnWriteArrayListCopyOnWriteArraySet
不支持添加null的集合有:
HashTableConcurrentHashMapConcurrentSkipListSetConcurrentlinkedDequeConcurrentlinkedQequelinkedBlockingDequelinkedBlockingQueueArrayBlockingQueuePriorityBlockingQueue
可能还有些许遗漏,欢迎大家在评论区补充。遇到这种问题,通过尝试或者查看源码就可以确定。



