11

I have following String Array tmp = [null, null, null, Mars, Saturn, Mars] coming after doing the operation - allSig[d3].split(" "); where allSig is an array of Strings. The null value is empty value in the array. Now I want to remove the null. For this I am using

tmp[indexNumber] != null is not working and giving true ; taking null as the value. Even if i am using "null" as a string is not working.

How to remove this.

public static String[] removeElements(String[] allElements) {
    String[] _localAllElements = new String[allElements.length];

    for (int i = 0; i < allElements.length; i++)
        if (allElements[i] != null)
            _localAllElements[i] = allElements[i];

    return _localAllElements;
}
Bharat Sinha
  • 13,973
  • 6
  • 39
  • 63
Kumar
  • 955
  • 5
  • 20
  • 50
  • Are the `"null"` always together at the beginning or end? – obataku Aug 17 '12 at 08:25
  • No First i created a array by this way - String[] x= new String[10]; then I added in the value by this way - x[a8] += " " + planetName1Tr[a9]; in this scenario in null value is added that is lyk - "null Sun Moon" etc. Now I want to remove this null. – Kumar Aug 17 '12 at 08:32
  • You can probably avoid having to clean anything at all. – obataku Aug 17 '12 at 08:51

6 Answers6

2

You're creating an array with same size as the original one. So it's the same as the original array, as you copy non null values and default values are null.

Do this :

public static String[] removeElements(String[] allElements) {
    // 1 : count
    int n = 0;
    for (int i = 0; i < allElements.length; i++)
        if (allElements[i] != null) n++;

    // 2 : allocate new array
    String[] _localAllElements = new String[n];

    // 3 : copy not null elements
    int j = 0;
    for (int i = 0; i < allElements.length; i++)
        if (allElements[i] != null)
            _localAllElements[j++] = allElements[i];

    return _localAllElements;
}
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • No reason at all for doing 2 passes. – obataku Aug 17 '12 at 08:30
  • 1
    @veer you need the number of not null strings to allocate a well sized array. Or you need to do another copy after, which is more expensive. – Denys Séguret Aug 17 '12 at 08:39
  • you only have to check for null once! – obataku Aug 17 '12 at 08:39
  • actually `Arrays.copyOf` is probably as fast as the manual copy you're doing, not to mention you'd have to compare each element against `"null"` twice ;) – obataku Aug 17 '12 at 08:44
  • You're changing the initial array. I don't. That's the reason you seem to make only one copy operation. But this is a detail. – Denys Séguret Aug 17 '12 at 08:45
  • Did you read my comment ? I you make a method giving a new array and leaving the source one unchanged (as in the question), you start by copying the array and so you make 2 copy operations while I make one. But as I yet said, this is a detail, you solution is perfectly correct (and shorter) and the differences, whose importance depend on the usage, are not worth the time spent in arguing... – Denys Séguret Aug 17 '12 at 08:53
2
public static String[] clean(final String[] v) {
  int r, w;
  final int n = r = w = v.length;
  while (r > 0) {
    final String s = v[--r];
    if (!s.equals("null")) {
      v[--w] = s;
    }
  }
  return Arrays.copyOfRange(v, w, n);
}

or

public static String[] clean(final String[] v) {
  int r, w, n = r = w = v.length;
  while (r > 0) {
    final String s = v[--r];
    if (!s.equals("null")) {
      v[--w] = s;
    }
  }
  final String[] c = new String[n -= w];
  System.arraycopy(v, w, c, 0, n);
  return c;
}

Works fine...

public static void main(final String[] argv) {
  final String[] source = new String[] { "Mars", "null", "Saturn", "null", "Mars" };
  assert Arrays.equals(clean(source), new String[] { "Mars", "Saturn", "Mars" });
}
obataku
  • 29,212
  • 3
  • 44
  • 57
2

Abstracting @az answer, this applies to any class type:

@SuppressWarnings("unchecked")
public static <T> T[] clean(T[] a) {
    List<T> list = new ArrayList<T>(Arrays.asList(a));
    list.removeAll(Collections.singleton(null));
    return list.toArray((T[]) Array.newInstance(a.getClass().getComponentType(), list.size()));
}
IvanRF
  • 7,115
  • 5
  • 47
  • 71
1

If you want the array to contain only the non-null values (i.e. the resulting array would be ["Mars", "Saturn", "Mars"]), then I would look at this as a two part problem.

First, you must identify what the size of the new array should be. From inspection, it's easy to see that it's 3, but you will need to need to count them to calculate this programmatically. You can do this by saying:

// Calculate the size for the new array.
int newSize = 0;
for (int i = 0; i < allElements.length; i++)    {
    if (allElements[i] != null) {
        newSize++;
    }
}

Secondly, you will need to create a new array with that size. Then you can put all of the non-null elements into your new array, as you have done above.

// Populate the new array.
String[] _localAllElements = new String[newSize];
int newIndex = 0;
for (int i = 0; i < allElements.length; i++) {
    if (allElements[i] != null) {
        _localAllElements[newIndex] = allElements[i];
        newIndex++;
    }
}

// Return the new array.
return _localAllElements;

You can just combine these two components as the new content of your results method. See the full combined code and live sample output here.

Jon Newmuis
  • 25,722
  • 2
  • 45
  • 57
0
public static String[] removeElements(String[] allElements) {
    String[] _localAllElements = new String[allElements.length];
    int j = 0;
    for (int i = 0; i < allElements.length; i++)
        if ( allElements[i] != null && !allElements[i].equals(""))
            _localAllElements[j++] = allElements[i];

    return _localAllElements;
}
sloth
  • 99,095
  • 21
  • 171
  • 219
0

This is a very old question but this Java 8+ solution might be useful to someone:

public static String[] removeElements(String[] allElements) { return Arrays.stream(allElements) .filter(Objects::nonNull) .collect(Collectors.toArray()); } or if you, like me, are a fan of readable code and don't want static methods to get in your way, you can simplify this even further using static imports:

public static String[] removeElements(String[] allElements) { return stream(allElements).filter(Objects::nonNull).collect(toArray()); }

Clint Eastwood
  • 4,995
  • 3
  • 31
  • 27
  • There is no `Collectors.toArray()`. To get a `String[]` from a Stream, you have to invoke `.toArray(String[]::new)` directly on the Stream. – Holger Jan 31 '19 at 17:06