Java細節:List可以add(null)嗎?

在寫代碼的時候,有時候遇到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;
}

參考
1、https://blog.csdn.net/krossford/article/details/83903851

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章