在Java中从字符串数组中删除空值

43
如何从Java字符串数组中删除空值?
String[] firstArray = {"test1","","test2","test4",""};

我需要像这样没有 null(空)值的 "firstArray"

String[] firstArray = {"test1","test2","test4"};

39
在Java中,null与“空字符串”完全不同。这是你的第一个问题。 - JSBձոգչ
1
null 不是 ""。"" 是一个空的,但完全有效的字符串。 - EboMike
那个数组中没有空值。但是,有一个空字符串(一个长度为0的非空字符串对象)。无论如何,你尝试了什么? - user166390
是的,你说得对。null与""是不同的。我只想删除所有空字符串,应该得到另一个没有空字符串的"字符串数组",正如我所提到的。 - Gnaniyar Zubair
那么您可能希望更新您的问题以反映您的意思是空字符串而不是null。 - Steve Kuo
可能是如何在Java中从数组中删除对象?的重复问题。 - McDowell
8个回答

85

如果你想避免数组操作时的常见错误,并且不想在数组中移动或删除元素,这里提供一种使用 List 的解决方案,可能会稍微啰嗦一些:

import java.util.ArrayList;
import java.util.List;

public class RemoveNullValue {
  public static void main( String args[] ) {
    String[] firstArray = {"test1", "", "test2", "test4", "", null};

    List<String> list = new ArrayList<String>();

    for(String s : firstArray) {
       if(s != null && s.length() > 0) {
          list.add(s);
       }
    }

    firstArray = list.toArray(new String[list.size()]);
  }
}

添加了null以展示空字符串实例("")与null之间的区别。

由于这个回答已经大约4.5年了,我添加了一个Java 8的例子:

import java.util.Arrays;
import java.util.stream.Collectors;

public class RemoveNullValue {
    public static void main( String args[] ) {
        String[] firstArray = {"test1", "", "test2", "test4", "", null};

        firstArray = Arrays.stream(firstArray)
                     .filter(s -> (s != null && s.length() > 0))
                     .toArray(String[]::new);    

    }
}

27

似乎没有人提到可以使用在Java 8中也可以与streams一起使用的nonNull方法来删除空值(但不是空字符串):

String[] origArray = {"Apple", "", "Cat", "Dog", "", null};
String[] cleanedArray = Arrays.stream(firstArray).filter(Objects::nonNull).toArray(String[]::new);
System.out.println(Arrays.toString(origArray));
System.out.println(Arrays.toString(cleanedArray));

输出结果为:

[Apple, , Cat, Dog, , null]

[Apple, , Cat, Dog, ]

如果我们也想包含空,则可以定义一个实用方法(在类 Utils 中):

public static boolean isEmpty(String string) {
        return (string != null && string.isEmpty());
    }

然后使用它来过滤物品,如下:

Arrays.stream(firstArray).filter(Utils::isEmpty).toArray(String[]::new);

我相信Apache common也提供了一个实用方法StringUtils.isNotEmpty,也可以使用。


Arrays.stream(firstArray).filter(Objects::nonNull).toArray(String[]::new); 对我很有用。当你必须使用数组而不是列表在已定义的函数中工作时,这是一个很好的解决方法,你不想重写它。 - Drizzle53

20

如果你想要向数组中添加/删除元素,我建议使用 List

String[] firstArray = {"test1","","test2","test4",""};
ArrayList<String> list = new ArrayList<String>();
for (String s : firstArray)
    if (!s.equals(""))
        list.add(s);

那么,如果你真的需要把它放回到一个数组中:

firstArray = list.toArray(new String[list.size()]);

哈哈。你实现了我描述的东西!:-) 我唯一的改进是在toArray中传递一个 new String[0] -- 它将根据需要创建一个具有正确大小的新数组。 - user166390
你应该使用 String.isEmpty() 而不是 String.equals("") - Steve Kuo
@Steve, 很多人都有和你一样的感觉。但就我个人而言,我认为s.equals("")更易读,抽象性较低。 - Kirk Woll
@DaveJarvis,很明显OP混淆了空字符串和null - Kirk Woll
2
你说得对,Kirk。然而NullPointerException的可能性仍然存在。那是一个bug。 - Dave Jarvis

4

这是我用来从一个不使用数组列表的数组中移除空值的代码。

String[] array = {"abc", "def", null, "g", null}; // Your array
String[] refinedArray = new String[array.length]; // A temporary placeholder array
int count = -1;
for(String s : array) {
    if(s != null) { // Skips over null values. Add "|| "".equals(s)" if you want to exclude empty strings
        refinedArray[++count] = s; // Increments count and sets a value in the refined array
    }
}

// Returns an array with the same data but refits it to a new length
array = Arrays.copyOf(refinedArray, count + 1);

最后一行存在一个偏移错误。应该是 count + 1 - coolguy

4
使用Google的guava库
String[] firstArray = {"test1","","test2","test4","",null};

Iterable<String> st=Iterables.filter(Arrays.asList(firstArray),new Predicate<String>() {
    @Override
    public boolean apply(String arg0) {
        if(arg0==null) //avoid null strings 
            return false;
        if(arg0.length()==0) //avoid empty strings 
            return false;
        return true; // else true
    }
});

2
沿用同样的方法,可以使用FunctionalJava库。 - user166390
@Emil 然后,你如何将 st 中的内容放回到 firstArray 中? - Abdull
@Abdull:不需要这样做,因为firstArray没有被修改。 这种过滤是懒惰的,即在迭代数组时发生。 - Emil
2
如果要避免空字符串,可以使用if(Strings.isNullOrEmpty(str))代替if(arg0==null) return false;。同样地,如果要避免空字符串,也可以使用if(arg0.length()==0) return false;。 - Sagar

3

这与之前发布的内容相当相似,但更易于阅读。

/**
 * Remove all empty spaces from array a string array
 * @param arr array
 * @return array without ""
 */
public static String[] removeAllEmpty(String[] arr) {
    if (arr == null)
        return arr;

    String[] result = new String[arr.length];
    int amountOfValidStrings = 0;

    for (int i = 0; i < arr.length; i++) {
        if (!arr[i].equals(""))
            result[amountOfValidStrings++] = arr[i];
    }

    result = Arrays.copyOf(result, amountOfValidStrings);

    return result;
}

它可能可读。但是代码看起来有点冗长。 - Prathap Reddy

1
一段友好于垃圾回收的代码:

public static<X> X[] arrayOfNotNull(X[] array) {
    for (int p=0, N=array.length; p<N; ++p) {
        if (array[p] == null) {
            int m=p; for (int i=p+1; i<N; ++i) if (array[i]!=null) ++m;
            X[] res = Arrays.copyOf(array, m);
            for (int i=p+1; i<N; ++i) if (array[i]!=null) res[p++] = array[i];
            return res;
        }
    }
    return array;
}

如果原始数组中不包含 null 值,则返回原始数组。它不会修改原始数组。


-1

这些是零长度的字符串,而不是 null。但如果你想要移除它们:

firstArray[0] refers to the first element
firstArray[1] refers to the second element

你可以这样将第二个移动到第一个位置:

firstArray[0]  = firstArray[1]

如果你针对元素[1,2],然后[2,3]等这样做,最终你将会把整个数组内容向左移位,消除第0个元素。你可以看到这是如何应用的吗?

1
那么问题就变成了:“你如何在Java中调整数组大小”? :-) - user166390
这并不是他想要的功能。它只是简单地复制数据,而没有做任何使数组变小的操作。 - mlathe
谢谢。但是如果我知道空字符串将出现的位置,我可以按照您所说的做。但是空字符串是动态生成的。我无法预测空字符串(零长度)将出现在哪个位置。 - Gnaniyar Zubair
是的,但s.size() == 0会告诉你一个字符串的长度为零。我的想法是让你遍历数组,在零长度元素上移动元素。这个问题非常简单,我认为这是一道作业题,不想直接给你答案,但显然这就是被投票赞同的答案。 耸肩 - Mud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接