How to efficiently remove all null elements from a ArrayList or String Array?

JavaPerformanceLoopsFor LoopArraylist

Java Problem Overview


I try with a loop like that

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

But it isn't nice. Can anyone suggest me a better solution?


Some useful benchmarks to make better decision:

While loop, For loop and Iterator Performance Test

Java Solutions


Solution 1 - Java

Try:

tourists.removeAll(Collections.singleton(null));

Read the Java API. The code will throw java.lang.UnsupportedOperationException for immutable lists (such as created with Arrays.asList); see this answer for more details.

Solution 2 - Java

As of 2015, this is the best way (Java 8):

tourists.removeIf(Objects::isNull);

Note: This code will throw java.lang.UnsupportedOperationException for fixed-size lists (such as created with Arrays.asList), including immutable lists.

Solution 3 - Java

list.removeAll(Collections.singleton(null));

> It will Throws UnsupportedException if you use it on Arrays.asList because it give you Immutable copy so it can not be modified. See below the code. It creates Mutable copy and will not throw any exception.

public static String[] clean(final String[] v) {
	List<String> list = new ArrayList<String>(Arrays.asList(v));
	list.removeAll(Collections.singleton(null));
	return list.toArray(new String[list.size()]);
}

Solution 4 - Java

Not efficient, but short

while(tourists.remove(null));

Solution 5 - Java

If you prefer immutable data objects, or if you just dont want to be destructive to the input list, you can use Guava's predicates.

ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))

Solution 6 - Java

 for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

Solution 7 - Java

Pre-Java 8 you should use:

tourists.removeAll(Collections.singleton(null));

Post-Java 8 use:

tourists.removeIf(Objects::isNull);

The reason here is time complexity. The problem with arrays is that a remove operation can take O(n) time to complete. Really in Java this is an array copy of the remaining elements being moved to replace the empty spot. Many other solutions offered here will trigger this issue. The former is technically O(n*m) where m is 1 because it's a singleton null: so O(n)

You should removeAll of the singleton, internally it does a batchRemove() which has a read position and a write position. And iterates the list. When it hits a null, it simply iterates the read position by 1. When they are the same it passes, when they are different it keeps moving along copying the values. Then at the end it trims to size.

It effectively does this internally:

public static <E> void removeNulls(ArrayList<E> list) {
    int size = list.size();
    int read = 0;
    int write = 0;
    for (; read < size; read++) {
        E element = list.get(read);
        if (element == null) continue;
        if (read != write) list.set(write, element);
        write++;
    }
    if (write != size) {
        list.subList(write, size).clear();
    }
}

Which you can explicitly see is an O(n) operation.

The only thing that could ever be faster is if you iterated the list from both ends, and when you found a null, you set its value equal to the value you found at the end, and decremented that value. And iterated until the two values matched. You'd mess up the order, but would vastly reduce the number of values you set vs. ones you left alone. Which is a good method to know but won't help much here as .set() is basically free, but that form of delete is a useful tool for your belt.


for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

While this seems reasonable enough, the .remove() on the iterator internally calls:

ArrayList.this.remove(lastRet);

Which is again the O(n) operation within the remove. It does an System.arraycopy() which is again not what you want, if you care about speed. This makes it n^2.

There's also:

while(tourists.remove(null));

Which is O(m*n^2). Here we not only iterate the list. We reiterate the entire list, each time we match the null. Then we do n/2 (average) operations to do the System.arraycopy() to perform the remove. You could quite literally, sort the entire collection between items with values and items with null values and trim the ending in less time. In fact, that's true for all the broken ones. At least in theory, the actual system.arraycopy isn't actually an N operation in practice. In theory, theory and practice are the same thing; in practice they aren't.

Solution 8 - Java

The Objects class has a nonNull Predicate that can be used with filter.

For example:

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());

Solution 9 - Java

Using Java 8, you can do this using stream() and filter()

tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())

or

tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())

For more info : Java 8 - Streams

Solution 10 - Java

Mainly I'm using this:

list.removeAll(Collections.singleton(null));

But after I learned Java 8, I switched to this:

List.removeIf(Objects::isNull);

Solution 11 - Java

There is an easy way of removing all the null values from collection.You have to pass a collection containing null as a parameter to removeAll() method

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);

Solution 12 - Java

This is easy way to remove default null values from arraylist

     tourists.removeAll(Arrays.asList(null));  

otherwise String value "null" remove from arraylist

       tourists.removeAll(Arrays.asList("null"));  

Solution 13 - Java

I played around with this and found out that trimToSize() seems to work. I am working on the Android platform so it might be different.

Solution 14 - Java

We can use iterator for the same to remove all the null values.

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
	if(itr.next() == null){
		itr.remove();
	}
}

Solution 15 - Java

I used the stream interface together with the stream operation collect and a helper-method to generate an new list.

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}

Solution 16 - Java

Using Java 8 this can be performed in various ways using streams, parallel streams and removeIf method:

List<String> stringList = new ArrayList<>(Arrays.asList(null, "A", "B", null, "C", null));
List<String> listWithoutNulls1 = stringList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
List<String> listWithoutNulls2 = stringList.parallelStream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
stringList.removeIf(Objects::isNull); //[A,B,C]

The parallel stream will make use of available processors and will speed up the process for reasonable sized lists. It is always advisable to benchmark before using streams.

Solution 17 - Java

Similar to @Lithium answer but does not throw a "List may not contain type null" error:

   list.removeAll(Collections.<T>singleton(null));

Solution 18 - Java

List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJuan de DiosView Question on Stackoverflow
Solution 1 - JavaLithiumView Answer on Stackoverflow
Solution 2 - JavaMarcGView Answer on Stackoverflow
Solution 3 - JavaAZ_View Answer on Stackoverflow
Solution 4 - JavaPeter LawreyView Answer on Stackoverflow
Solution 5 - Javauser1563987View Answer on Stackoverflow
Solution 6 - JavaMat MannionView Answer on Stackoverflow
Solution 7 - JavaTatarizeView Answer on Stackoverflow
Solution 8 - JavaJeffFView Answer on Stackoverflow
Solution 9 - JavaJad ChahineView Answer on Stackoverflow
Solution 10 - JavaMaged AlmaweriView Answer on Stackoverflow
Solution 11 - JavashivView Answer on Stackoverflow
Solution 12 - JavaJobin_vibesView Answer on Stackoverflow
Solution 13 - JavatheblitzView Answer on Stackoverflow
Solution 14 - JavaamitView Answer on Stackoverflow
Solution 15 - JavaMabiView Answer on Stackoverflow
Solution 16 - Javaakhil_mittalView Answer on Stackoverflow
Solution 17 - JavaHannahCarneyView Answer on Stackoverflow
Solution 18 - JavacunhafView Answer on Stackoverflow