空ArrayList和具有null元素的ArrayList之间的区别?

mel*_*182 6 java collections null list arraylist

我正在为一个解析JSON的REST服务编写一些验证器,我发现了一些听起来很奇怪的东西(我根本不是JAVA专家).

考虑使用两个ArrayLists:

ArrayList<Object> list1 = new ArrayList<Object>();
ArrayList<Object> list2 = new ArrayList<Object>();
Run Code Online (Sandbox Code Playgroud)

两个列表都有一些共同点:它们完全是空的(或者是空元素).但如果我这样做:

list1.add(null);
Run Code Online (Sandbox Code Playgroud)

虽然两者都完全是空的,但它们的行为完全不同.并且为了使一些方法的结果非常不同:

System.out.println(list1.contains(null));  //prints true!
System.out.println(list2.contains(null));  //prints false

System.out.println(CollectionUtils.isNotEmpty(list1));  //prints true
System.out.println(CollectionUtils.isNotEmpty(list2));  //prints false

System.out.println(list1.size());  //prints 1
System.out.println(list2.size());  //prints 0
Run Code Online (Sandbox Code Playgroud)

做一些研究,并查看每种方法的实现,您可以确定这些差异的原因,但仍然不明白为什么区分这些列表是有效的或有用的.

  • 为什么添加(item)不验证item!= null
  • 如果列表中充满空值,为什么包含(null)表示为false

提前致谢!!!

编辑:

我大多同意答案,但我还没有说服所有人.这是删除方法的实现:

/**
 * Removes the first occurrence of the specified element from this list,
 * if it is present.  If the list does not contain the element, it is
 * unchanged.  More formally, removes the element with the lowest index
 * <tt>i</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
 * (if such an element exists).  Returns <tt>true</tt> if this list
 * contained the specified element (or equivalently, if this list
 * changed as a result of the call).
 *
 * @param o element to be removed from this list, if present
 * @return <tt>true</tt> if this list contained the specified element
 */
public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}


/*
 * Private remove method that skips bounds checking and does not
 * return the value removed.
 */
private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}
Run Code Online (Sandbox Code Playgroud)

所以,现在如果我这样做:

ArrayList<Object> list = new ArrayList<Object>();
list.add(null);
System.out.println(list.contains(null)); //prints true!
list.remove(null);
System.out.println(list.contains(null));  //prints false!
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

dsh*_*dsh 12

一个包含列表null不是 空的.它包含null.列表允许包含null,因此如果需要,可以将null放入其中.

  • "*列表允许包含null*"可能会产生误导,因为不能保证*all*list会这样做.但是在"ArrayList"的情况下确实如此. (5认同)
  • @ melli-182差别是一个是空的,一个有*东西*(一个"null").写一个循环来打印元素,你会看到一个循环体执行零次而没有输出,一个用一行输出执行一次.如果你试图`.get(0)`,其中一个将抛出一个'ArrayIndexOutOfBounds`异常,另一个将返回索引为0的`null`值. (3认同)