在写代码的时候,有时候遇到for循环,写到下面的时候有一点犹豫。
List<Data> dataList = ...;
for (Data d : dataList) {
if (d != null) { // 需要这个判断吗?
// ...
}
}
产生上述疑问,究其原因在于对List源码不熟悉,虽然知道List接口有LinkedList(基于链表实现)、ArrayList(基于数组实现)等实现类,但其执行add方法的细节没关注,就会产生如题的疑惑。本文先得出结论,最后再去分析其中的原因。
在本地写test代码,往List中add null对象,然后再做遍历。
private void printList() {
List<Integer> dataList = new ArrayList<>();
dataList.add(1);
dataList.add(null);
dataList.add(null);
for (Integer d : dataList) {
System.out.println(d);
}
System.out.println("------------------------");
for (Integer d : dataList) {
if (d != null) { // 需要这个判断吗?
System.out.println(d);
}
}
}
测试函数输出
1
null
null
------------------------
1
针对问题:List可以add(null)吗?答案是肯定的,null对象是可以添加到列表中。这一点通过上述例子也很好理解。
理解此问题的关键点在于ArrayList底层的原理,针对本问题重点在于:
- List底层是数组即,Object[] elementData,数组对元素没限制。这一点可以通过源码解释:
/**
* This helper method split out from add(E) to keep method
* bytecode size under 35 (the -XX:MaxInlineSize default value),
* which helps when add(E) is called in a C1-compiled loop.
*/
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
- 关于Java对象是否能处理null,不要与Hashmap和Hashtable混淆,HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行。这一点通过源码解释:
Hashmap底层是由数组、链表、红黑色组成。数组的下标通过key值决定,
Node<K,V>[] table;
// key为null时,哈希值为0
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
// 数组下标计算方式
tab[i = (n - 1) & hash
Hashtable底层是由数组、链表组成。数组的下标通过key值决定,
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// key为null的话,key.hashCode()就会报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<K,V> entry = (Entry<K,V>)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;
}