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

I encode some validators for the REST service that parse JSON, and I found out something audible for me (I'm not a JAVA expert at all

)

Consider the presence of two ArrayLists :

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

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

 list1.add(null); 

Although both of them remain completely empty , they have completely different types of behavior. 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 

By doing some research and looking at the implementation of each of these methods, you can determine the cause of these differences, but you still don’t understand why it would be useful or useful to distinguish between these lists.

  • Why add (element) doesn't check if item! = Null ?
  • Why does it contain (null) say false if the list is filled with nulls ?

Thanks in advance!

EDIT:

I basically agree with the answers, but I'm still not convinced. This is the implementation of the remove method:

 /** * 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 am I missing?

+5
source share
5 answers

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

+11
source

An ArrayList explicitly allowed and can store null values ​​because they may make sense for your program. An empty list is empty (i.e. does not contain anything, not even null ). After successful add (null) (returns true for signal success), the list should obviously return true in contains (null). In fact, you can even remove (null) from this list, and it will be empty again.

+3
source

Fortunately, you do not have to be a Java expert or an expert.

The best way to think of it as parking. An array with zero elements is like a parking lot in which there is nothing. An empty array is similar to parking plans.

0
source

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

null is a value that any ArrayList can contain as an element. It is clear that in this case the list has at least one element and, therefore, is not empty. No matter what the initial state of the List , if the call to this add(null) in this list completes normally, then the list is not empty. Similarly, each null element in a list contributes to its size.

Why does add(item) not check if item!=null ?

Ask Joshua Bloch . He developed it. Most people consider him a pretty smart guy and find the collection APIs very successful.

Seriously, this is a design choice that List can contain null elements. (Implementations are allowed to reject zeros, but ArrayList , as a universal implementation, accepts them).

Why does it contain (null) says false if the list is filled with zeros?

This is not true. Do not tell me about it - the data that you present also contradict you.

0
source

All the confusion stems from the incorrect initial assumption that the ArrayLists you created are filled with zeros. They are not, they are completely empty , which means that they have zero elements . That way you get false if you call contains(null) on them, and true when you call isEmpty() .

As soon as you add null to list1, it ceases to be empty and really contains a null element - list2 is still empty and still does not contain null .

In the last code example, the second call to Collections.isNotEmpty definitely does not return true . There was one null item in the list, you deleted it, so it is empty again.

Basic tricks:

  • Calling either an empty constructor or a constructor with an initial capacity of ArrayList creates an empty list . This list does not contain any elements, not even null .
  • null is a perfectly valid ArrayList element . Cases where this may be useful are not extremely common, but they exist.
0
source

Source: https://habr.com/ru/post/1236735/


All Articles