4

所以假设我创建了一个有 5 个空格的数组,就像这样 - String[] myArray = new String[5]。然后假设我定义了其中一些项,但将其中一些项保留为空(或 Java 术语用于未定义数组项/变量的任何内容),如下所示:

myArray[0] = "foo";
myArray[2] = "bar";
myArray[4] = "foobar";

有没有办法我可以“缩小”该数组,挤出所有空项目(不改变它的大小)?这样“foo”的索引保持在0,但“bar”的索引变为1,而“foobar”驻留在2,最后2个空格是空的?长话短说 - 在数组中的项目周围洗牌,将所有空项目推到最后,同时保持其他项目的相对顺序。是否已经有预定义的 Java 方法,或者我需要自己制作?

4

6 回答 6

5

您可以使用以下方法(没有 Collections 实例的开销):

import java.util.Arrays;

public class ArraySample {

    public static void main(final String[] args) {
        String[] src = new String[] { "foo", null, "bar", null, "foobar" };
        String[] dest = new String[src.length];

        int i = 0;
        for (String s : src) {
            if (s != null) {
                dest[i++] = s;
            }
        }

        System.out.println(Arrays.toString(src));
        System.out.println(Arrays.toString(dest));
    }

}
于 2012-06-24T09:54:31.660 回答
5

您可以仅使用源数组来执行此操作:

    String[] src = new String[] { "foo", "foo3", null,null, "bar", null,null, "foobar", "foo2", null,"foo5",null };
    int lastNullIdx = -1;

    for (int i=0; i <src.length ; i++) {
        if (src[i] == null) {
            if(lastNullIdx==-1)lastNullIdx=i;
        }
        else if(lastNullIdx!=-1){
            src[lastNullIdx++]=src[i];
            src[i]=null;
        }
    }

    System.out.println(Arrays.toString(src));
于 2012-06-24T10:12:17.940 回答
1

不要以为有办法。如果有类似的东西,它会在 java.util.Arrays 中。我会这样做

String[] src = new String[] { "foo", null, "bar", null, "foobar" };

for (int c = 0, j = 0; c < src.length; c++) {
    if (src[c] != null) {
        src[j++] = src[c];
        src[c] = null;
    }
}

编辑:

String[] src = new String[] { "foo", null, "bar", null, "foobar" };
Comparator<String> NEW_ORDER = new Comparator<String>() {
    public int compare(String e1, String e2) {
        if(e1 == null)return 1;
        if(e2 == null)return -1;
        return 0;
    }
Arrays.sort(src, NEW_ORDER);

应该也可以,因为 Arrays.sort 是一种稳定的排序,但我认为另一种解决方案更好,因为它的 O(n) 而不是 O(n log n)

于 2012-06-24T10:32:40.267 回答
1

就地缩小,更简单的代码:

public static String[] minify(String[] x) {
  int d = 0;
  for (String s : x) if (s != null) x[d++] = s;
  while (d < x.length) x[d++] = null;
  return x;
}

public static void main(String[] args) {
  System.out.println(Arrays.toString(
      minify(new String[] {"foo", null, "bar", null, "foobar"})));
}
于 2012-06-24T10:37:27.937 回答
1

使用函数式java ,

array(myArray).filter(new F<String, Boolean>() {
  public Boolean f(String s) { 
    return s != null; 
  }
});

这将保留满足给定条件的元素。结果将是由 . 返回的新数组filter

编辑:

抱歉,我之前看错了问题。以下是如何将nulls 挤出到右侧。

array(myArray).sort(
  booleanOrd.comap(new F<String, Boolean>() {
    public Boolean f(String s) {
      return s == null;
    }
  })
);
于 2012-06-24T10:40:14.170 回答
0

Java 已经使用 Arrays.sort(T[] a, Comparator c) 方法为此类排序问题做好了准备:

Arrays.sort(myArray, new StringNullComparator());

class StringNullComparator implements Comparator<String> {

    @Override
    public int compare(String s1, String s2)
    {
        if(s1==null && s2!=null) return 1;
        else if(s1!=null && s2==null) return -1;
        else return 0;
    }
}

这样,您甚至可以通过反转 compare 方法返回的值来将空值排序为较低的 indecees。

于 2012-06-24T11:06:42.957 回答