开发者

How to remove null from an array in java

开发者 https://www.devze.com 2023-04-01 14:46 出处:网络
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.

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)
            {
               开发者_Go百科 a2[j]=a[j];
            }
        else if(j>i)
        {
            a2[j]=a[j+1];
        }
    }

    a=a2;
}

Thanks in advance!


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]);
}


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)


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;
}


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;
}


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);
}


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.


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.


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;
}


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.


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);


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!


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号