panther
panther

Reputation: 61

How to remove null from an array in java

I've written a method to remove null-values from an array i need in a program. The method, however, doesn't seem to work, the null values won't go away. This is my code so far.

public void removeNull(String[] a)
{
       for(int i=0; i<a.length; i++)
    {
        if(a[i] == null)
        {
            fillArray(a, i);
        }
    }
}

public void fillArray(String[] a, int i)
{
    String[] a2 = new String[a.length-1];

    for(int j=0; j<a2.length; j++)
    {
            if(j<i)
            {
                a2[j]=a[j];
            }
        else if(j>i)
        {
            a2[j]=a[j+1];
        }
    }

    a=a2;
}

Thanks in advance!

Upvotes: 5

Views: 38559

Answers (12)

Matvey Zhuravel
Matvey Zhuravel

Reputation: 174

Streams API version of the solution:

SomeClass[] array = new SomeClass[N];
...
array = Arrays.stream(array).filter(Objects::nonNull).toArray(SomeClass[]::new);

(I post this down to maybe get some thoughts on applicability, relative performance etc)

Upvotes: 9

David_G
David_G

Reputation: 111

hi everyone first of all i want to appologize for my english im learning at this moment and this is my first post so i want to try to put my solution about the problem here it is

String[] removeNulls(String[] nullsArray) {
    int countNulls = 0;

    for (int i = 0; i < nullsArray.length; i++) { // count nulls in array
        if (nullsArray[i] == null) {
            countNulls++;
        }
    }
    // creating new array with new length (length of first array - counted nulls)
    String[] nullsRemoved = new String[nullsArray.length - countNulls];

    for (int i = 0, j = 0; i < nullsArray.length; i++) {

        if (nullsArray[i] != null) {
            nullsRemoved[j] = nullsArray[i];
            j++;
        }
    }
    return nullsRemoved;
}

Upvotes: 5

Garrett Hall
Garrett Hall

Reputation: 30042

I would advocate doing it the simple way unless performance is really a problem:

public String[] removeNull(String[] a) {
   ArrayList<String> removedNull = new ArrayList<String>();
   for (String str : a)
      if (str != null)
         removedNull.add(str);
   return removedNull.toArray(new String[0]);
}

Upvotes: 7

Serge Slipchenko
Serge Slipchenko

Reputation: 21

This way would be faster:

private static String[] removeNulls(String[] strs) {
    int i = 0;
    int j = strs.length - 1;
    while (i <= j) {
        if (strs[j] == null) {
            --j;
        } else if (strs[i] != null) {
            ++i;
        } else {
            strs[i] = strs[j];
            strs[j] = null;
            ++i; --j;
        }
    }


    return Arrays.copyOfRange(strs, 0, i);
}

Upvotes: 2

You have two options:

  1. Create new array that length is same as the input, then assign to it not null values and add the substract it to the count of not null elememts .

    Example in 0xJoKe answer.

  2. If You need to work only sutch array you could create an adapter for it.

    public class NullProofIterable<T> implements Iterable<T>{
    
    private final T[] array;
    
    public NullProofIterable(T[] array){
        this.array = array;
    }
    
    @Override
    public Iterator<T> iterator() {
        return new NullProofIterator<T>(this.array);
    }
    
    
    private static class NullProofIterator<T> implements Iterator<T> {
    
        private final T[] array;
        private final int index = 0;
    
        private NullProofIterator(T[] array) {
            this.array = array;
        }
    
        @Override
        public boolean hasNext() {
    
            return this.index < this.array.length;
        }
    
        @Override
        public T next() {
            return this.array[this.index];
        }
    
        @Override
        public void remove() {
            throw new RuntimeException("Remove not allowed in this iterator");
        }
    
    }
    
    }
    

Then in source code, only thing you have to do is:

for(String str : new NullProofIterable<String>(strArray)) {
    //Perform action on not null string         
}

The second option is very fancy usage of != null condition bu it might be helful when a method need to return some data.

Upvotes: 0

Charliemops
Charliemops

Reputation: 769

Well, more people said it before... but I also want to emphasize this solution:

You can use some type of Collection, like ArrayList or List and add only the not null elements. Finally you must return the new String[] formed by the Collection.

Here an example where you can check the correctness:

import java.util.ArrayList;

public class NullRemove {

    public static String[] removeNull(String[] a) {
        ArrayList<String> aux = new ArrayList<String>();
        for (String elem : a) {
            if (elem != null) {
                aux.add(elem);
            }
        }
        return (String[]) aux.toArray(new String[aux.size()]);
    }
    public static void main(String[] args) {
        String[] init = new String[]{"aaa", null, "bbb", "ccc", null, "ddd", 
            "eee", "fff", null};

        String[] result = NullRemove.removeNull(init);

        System.out.println("Start Check result");

        for (String elem : result) {
            if (elem == null) System.out.println("NULL element");
        }

        System.out.println("End Check result");
    }
}

The for with the code don't print anything cause there is any null element :)

Regards!

Upvotes: 0

KLE
KLE

Reputation: 24169

When removing values in an array, the size changes so you can't keep the same array (you could push the nulls at the end).

The structure close to an array that has a auto-adjustable size is an ArrayList. One option would be :

String[] inputs;
List<String> items = new ArrayList<String>(inputs.length);
for(String input : inputs) {
   if (input != null) {
      items.add(input);
   }
}
String[] outputs = items.toArray(new String[items.size()]);

Performance might be a bit less than working directly with arrays, but because an array has a fixed size, you would need two loops with arrays :

  • one to count the number of non-null values
  • after building the array, the same loop to copy the values.

This might not have an ideal performance either, and it is really much more complex to get it right...


Another approach would be to move the nulls at the end, then create a shorter array that wouldn't include the nulls. The idea would be :

String[] strings;
int writeIndex = 0;
int max = strings.length;
for(int readIndex = 0; readIndex < max; readIndex++) {
   String read = strings[readIndex];
   if (read != null) {
      strings[writeIndex++] = read;
   }
}
String[] outputs = new String[writeIndex];
System.arraycopy(strings, 0, ouputs, 0, writeIndex);

Upvotes: 0

nidu
nidu

Reputation: 559

This way you can remove nulls in one cycle, but it will not resize array:

public static void removeNull(String[] a) {
    int nullCount = 0;
    for (int i = 0; i < a.length; i++) {
        if (a[i] == null) {
            nullCount++;
        } else {
            a[i-nullCount] = a[i];
        }
    }
}

This one creates new array, but includes two cycles:

public static String[] removeNull(String[] a) {
    int nullCount = 0;
    for (int i = 0; i < a.length; i++) {
        if (a[i] == null) nullCount++;
    }
    String[] b = new String[a.length-nullCount];
    int j = 0;
    for (int i = 0; i < a.length; i++) {
        if (a[i] != null) b[j++] = a[i];
    }
    return b;
}

You can think on optimizing that code using System.arraycopy. I hope the code works.

Upvotes: 0

0xJoKe
0xJoKe

Reputation: 853

Try this (I didn't test it):

public String[] removeNull(String[] a) {
    String[] tmp = new String[a.length];
    int counter = 0;
    for (String s : a) {
        if (s != null) {
            tmp[counter++] = s;
        }
    }
    String[] ret = new String[counter];
    System.arraycopy(tmp, 0, ret, 0, counter);
    return ret;
}

Upvotes: 0

skaz
skaz

Reputation: 22640

A couple of things:

  1. Don't you wantString[] a2 = new String[a.length-1];` to be

String[] a2 = new String[a.length];

Won't making it length - 1 make it too short?

  1. You need a case for i == j in your code. This is why the nulls aren't getting updated.

  2. What problem are you trying to solve with the second function? It seems complicated given what I thought your problem was.

Upvotes: 0

Vivien Barousse
Vivien Barousse

Reputation: 20895

I can see two errors in your code:

  • Your method fillArray doesn't cover the case i == j
  • Your assignation a = a2; doesn't have the effect you think it might have. Arguments are passed by value in Java, and your assignment does NOT change the value of a in your first method. Try returning an instance to a2 in fillArray, and assign this value to a in removeNull.

Upvotes: 1

adarshr
adarshr

Reputation: 62613

You can't change the reference to a variable in a method and expect it to be reflected in the calling method.

You'll instead have to return the new array.

public String[] removeNull(String[] a)
{
    for(int i=0; i<a.length; i++)
    {
        if(a[i] == null)
        {
            a = fillArray(a, i);
        }
    }

    return a;
}

public String[] fillArray(String[] a, int i)
{
    String[] a2 = new String[a.length-1];

    for(int j=0; j<a2.length; j++)
    {
            if(j<i)
            {
                a2[j]=a[j];
            }
        else if(j>i)
        {
            a2[j]=a[j+1];
        }
    }

    return a2;
}

Upvotes: 2

Related Questions