2011-08-29 152 views
2

我已经写了一个方法来从程序中需要的数组中删除空值。然而,该方法似乎并不奏效,空值不会消失。这是我的代码到目前为止。如何从java中的数组中删除null

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

在此先感谢!

+0

这里可能同样的问题[!链接](http://stackoverflow.com/questions/4150233/remove-null-value-from-string-array-in -java) – Gatekeeper

+0

是否有可能不允许空值进入数组? –

回答

2

您不能在方法中更改对变量的引用,并希望它在调用方法中反映出来。您将不得不返回新数组。

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

我可以看到你的代码的两个错误:

  • 你的方法fillArray没有覆盖的情况下i == j
  • 你分配a = a2;没有你认为它可能有效果。参数在Java中以值传递,并且您的分配不会在第一个方法中更改值a。尝试将实例返回a2,fillArray,并将此值分配给removeNull中的a
0

几件事情:

  1. Don't you want字符串[] A2 =新的String [则为a.length-1];`是

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

会不会使它length - 1使它太短?

  1. 您的代码需要一个i == j的情况。这就是空值没有更新的原因。

  2. 你想用第二个函数解决什么问题?看起来很复杂,因为我认为你的问题是。

0

试试这个(我没有测试):

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

你为什么要在最后复制它ret? –

+0

因为可能不是每个字段都是必需的(这意味着我在末尾有空值) – 0xJoKe

5

我会主张这样做的简单的方法,除非性能真的有问题:

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

+1 - 最简单的代码是最好的,除非存在对性能的*真实*需求。 –

+0

+1你真的想给'remove'变量赋一个'ArrayList'类型吗?我在想'列表',以尽量减少对实际类型的依赖。 – KLE

+0

@KLE如果我返回ArrayList,这将是一个好主意,因为我可能想通过多态性来更改实现,但对于小方法内的类型,这并不重要。 –

0

当移除值在一个数组中,大小发生变化,所以你不能保持相同的数组(你可以在最后推零)。

接近具有自动调整大小的数组的结构是ArrayList。一种选择是:

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

性能可能会比直接使用数组有点少,但由于阵列具有固定的大小,则需要两个循环使用数组:

  • 一个用于计数非空值的数量
  • 构建数组后,同一个循环复制值。

这可能不会有理想的性能要么,它是真正的要复杂得多做得正确...


另一种方法是在年底移动零点,然后创建一个不包含空值的较短阵列。这个想法是:

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

这样你可以删除在一个周期内空,但不会调整数组:

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

这一个创造新的阵列,但包括两个周期:

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

您可以考虑使用System.arraycopy优化该代码。我希望代码有效。

+0

我不认为你可以使用arrayCopy进行优化。使用arrayCopy的任何好处都会在你计算出使用它的时间内消失。我能想到的唯一优化是测试nullCount是否为零,如果是,返回原始数组。 –

0

你有两个选择:

  1. 创建新数组的长度是一样的输入,然后分配给它不是空值与它。减去添加到NOT NULL elememts的计数。

    0xJoKe答案中的示例。

  2. 如果你只需要工作sutch数组,你可以为它创建一个适配器。

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

然后在源代码中,只有你要做的事情是:

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

第二个选择是很花哨的用法= NULL条件BU它可能是helful时的方法需要返回一些数据。

0

好,越来越多的人之前说的...但我也想强调这一点的解决方案:

您可以使用某种类型的集合,如ArrayList或列表,并添加只有未null元素。最后,你必须返回由集合形成的新的String []。

下面的例子,你可以检查的正确性:

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

的与代码不显示任何信息的原因有任何null元素:)

商祺!

0

这样会更快:

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