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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33902195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:16:08  来源:igfitidea点击:

Difference between an empty ArrayList and an ArrayList with null elements?

javalistarraylistcollectionsnull

提问by melli-182

I am coding some validators for a REST service which parse a JSON and I found out something that sounds wierd for me (I am not a JAVA expertat all).

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

Consider having two ArrayLists:

考虑有两个ArrayLists

ArrayList<Object> list1 = new ArrayList<Object>();
ArrayList<Object> list2 = new ArrayList<Object>();

Both lists have something in common: they are completely empty(or full of null elements). But if I do:

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

list1.add(null);

Although both remain completely empty, they have completely different behaviors. And to make some methods the results are very different:

虽然两者都保持完全空白但它们的行为却完全不同。并制作一些方法结果非常不同

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

Doing some research, and looking at the implementation of each of these methods, you can determine the reason for these differences, but still do not understand why it would be valid or useful to differentiate between these lists.

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

  • Why add(item)doesnt validate if item!=null?
  • Why contains(null)says falseif the list is full of nulls?
  • 为什么add(item)不验证item!=null
  • 如果列表充满空值,为什么contains(null)false

Thanks in advance!!!

提前致谢!!!

EDIT:

编辑:

I am mostly agree whit the answers, but I'm not yet convinced all. This is the implementation of the method remove:

我基本上同意这些答案,但我还没有完全相信。这是remove方法的实现:

/**
 * 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
}

So, now if i do:

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

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!

what I'm missing?

我错过了什么?

回答by dsh

A list containing nullis NOTempty. It contains null. Lists are allowed to contain null, so you can put null in it if you want.

一个包含列表null不是空的。它包含null. 列表允许包含空值,因此您可以根据需要将空值放入其中。

回答by Wormbo

An ArrayListexplicitly is allowed and able to store nullvalues, because they might be meaningful to your program. And empty list is empty (i.e. doesn't contain anything, not even null. After you successfully add(null) (it returns trueto signal success), the list must obviously return trueon contains(null) as well. In fact, you can even remove(null) from that list and it will be empty again.

一个ArrayList明确是允许的,能够存储的null值,因为它们可能是有意义的程序。而空列表为空(即不包含任何东西,甚至没有null。你成功后添加(空)(它返回true到信号成功),列表显然必须返回true(空)也是如此。事实上,你甚至可以从该列表中删除(null),它将再次为空。

回答by soulsabr

Fortunately you don't have to be a java expert or an expert at all.

幸运的是,您根本不必成为 Java 专家或专家。

The best way to think of this is like a parking lot. An array with null elements is like a parking lot with nothing parked in it. An empty array is like the plans for a parking lot.

考虑这个的最好方法是像一个停车场。包含空元素的数组就像一个没有停放任何东西的停车场。一个空数组就像一个停车场的计划。

回答by John Bollinger

A Listis empty if it contains zero elements. This is both the natural meaning of the term and the test performed by the isEmpty()method.

List如果A包含零个元素,则为空。这既是该术语的自然含义,也是该isEmpty()方法执行的测试。

nullis a value that any ArrayListmay contain as an element. Clearly, in that case the list has at least one element, and therefore is not empty. No matter what the initial state of a List, if an invocation of add(null)on that list completes normally then afterward the list is not empty. Similarly, each nullelement in a list contributes to its size.

null是任何ArrayList可以作为元素包含的值。显然,在那种情况下,列表至少有一个元素,因此不是空的。无论 a 的初始状态如何List,如果add(null)对该列表的调用正常完成,则此后该列表不为空。类似地,null列表中的每个元素都会影响其大小。

Why add(item)doesnt validate if item!=null?

为什么add(item)不验证 if item!=null

Ask Joshua Bloch. He designed it. Most people take him to be a pretty smart guy, and consider the Collections API a highly successful effort.

约书亚·布洛赫。他设计的。大多数人认为他是一个非常聪明的人,并认为 Collections API 是一项非常成功的努力。

Seriously, it is a design choice that Lists may contain nullelements. (Implementations are permitted to reject nulls, but ArrayList, as a general-purpose implementation, accepts them).

说真的,Lists 可能包含null元素是一种设计选择。(允许实现拒绝空值,但ArrayList作为通用实现,接受它们)。

Why contains(null) says false if the list is full of nulls?

如果列表充满空值,为什么 contains(null) 说 false?

It doesn't. Don't just take my word for it -- the data you present also contradict you.

它没有。不要只相信我的话——你提供的数据也与你相矛盾。

回答by Matej

The entire confusion stems from the incorrect initial assumption that the ArrayLists you created are full of nulls. They are not, they are completely empty- meaning they have zero elements. As such, you will get falseif you call contains(null)on them, and truewhen you call isEmpty().

整个混乱源于错误的初始假设,即您创建的 ArrayList 充满了空值。它们不是,它们完全是空的——这意味着它们有零个元素。因此,你会得到错误的,如果你叫contains(null)上他们,当你调用isEmpty()

Once you added null to list1, it ceased to be empty, and indeed contains a null element - list2 is still empty and still doesn't contain null.

一旦您将 null 添加到 list1 ,它就不再是空的,并且确实包含一个 null 元素 - list2 仍然是空的并且仍然不包含 null

In your last code sample, the second call to Collections.isNotEmpty definitely does not return true. The list had one null element, you removed it, so it's empty again.

在您的最后一个代码示例中,对 Collections.isNotEmpty 的第二次调用肯定不会返回 true。列表有一个空元素,你删除了它,所以它又是空的。

The main take-aways here are:

这里的主要收获是:

  • Calling either the empty constructor, or the constructor with initial capacity of an ArrayList creates an empty list. This list does not contain any elements, not even null.
  • null is a perfectly valid element of an ArrayList. The cases where this might be useful are not extremely common but they do exist.
  • 调用空构造函数或具有 ArrayList 初始容量的构造函数会创建一个空列表。此列表不包含任何元素,甚至不包含null
  • null 是一个完全有效的 ArrayList 元素。这可能有用的情况并不常见,但确实存在。