如何从Java中删除数组中的对象?

ram*_*yac 75 java arrays data-manipulation data-structures

给定n个对象的数组,假设它是一个字符串数组,它具有以下值:

foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
Run Code Online (Sandbox Code Playgroud)

如何删除/删除数组中等于"a"的所有字符串/对象?

Chr*_*ung 106

[如果你想要一些现成的代码,请滚动到我的"Edit3"(剪辑后).剩下的就是后人.]

充实Dustman的想法:

List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
Run Code Online (Sandbox Code Playgroud)

编辑:我现在正在使用Arrays.asList而不是Collections.singleton:singleton仅限于一个条目,而该asList方法允许您添加其他字符串以便稍后过滤:Arrays.asList("a", "b", "c").

Edit2:上面的方法保留了相同的数组(所以数组的长度仍然相同); 最后一个元素设置为null.如果您想要一个完全符合要求的数组,请改用:

array = list.toArray(new String[0]);
Run Code Online (Sandbox Code Playgroud)

编辑3:如果您经常在同一个班级中使用此代码,您可以考虑将其添加到您的班级:

private static final String[] EMPTY_STRING_ARRAY = new String[0];
Run Code Online (Sandbox Code Playgroud)

然后功能变为:

List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);
Run Code Online (Sandbox Code Playgroud)

然后,这将停止使用无用的空字符串数组乱丢您的堆,否则new每次调用函数时都会对其进行编辑.

愤世嫉俗者的建议(见评论)也将有助于堆乱扔垃圾,为了公平起见,我应该提一下:

array = list.toArray(new String[list.size()]);
Run Code Online (Sandbox Code Playgroud)

我更喜欢我的方法,因为可能更容易使显式大小错误(例如,调用size()错误的列表).

  • 为什么不使用list.toArray(new String [list.size()])而不是new String [0],因为如果大小正确,代码将使用新数组? (2认同)

Vit*_*nko 27

Java 8中的替代方案:

String[] filteredArray = Arrays.stream(array)
    .filter(e -> !e.equals(foo)).toArray(String[]::new);
Run Code Online (Sandbox Code Playgroud)

  • 虽然整洁,但与System.arraycopy相比,这将是非常低效的.可能不应该在实际代码中执行此操作. (6认同)

Dus*_*man 20

List用数组制作一个数组Arrays.asList(),并调用remove()所有适当的元素.然后调用toArray()'List'再次返回一个数组.

性能不是很好,但是如果你正确地封装它,你总是可以在以后更快地做一些事情.

  • 这有什么关系?@Chris指出由`Arrays.asList()`生成的列表不支持`remove()`.这个答案完全无效吗?看起来好像有些评论被删除了,所以我不知道是否讨论过这个问题. (7认同)
  • 你的评论:没关系,你很快就会习惯它.:-)我发布了我的帖子,因为我不想让读者知道可以从Arrays.asList()的结果中删除元素(这是一个不可变的列表),所以我认为一个例子可以解决这个问题.:-) (3认同)

小智 15

你可以随时做:

int i, j;
for (i = j = 0; j < foo.length; ++j)
  if (!"a".equals(foo[j])) foo[i++] = foo[j];
foo = Arrays.copyOf(foo, i);
Run Code Online (Sandbox Code Playgroud)


bug*_*gs_ 6

您可以使用外部库:

org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
Run Code Online (Sandbox Code Playgroud)

它是在项目Apache Commons Lang http://commons.apache.org/lang/


Ali*_*Ali 5

见下面的代码

ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
Run Code Online (Sandbox Code Playgroud)


Ale*_*you 5

如果您需要从数组中删除多个元素而不将其转换为List或创建额外的数组,您可以在 O(n) 中执行此操作,而不依赖于要删除的项目数。

这里a是初始数组,int... r是要删除的元素的不同有序索引(位置):

public int removeItems(Object[] a, int... r) {
    int shift = 0;                             
    for (int i = 0; i < a.length; i++) {       
        if (shift < r.length && i == r[shift])  // i-th item needs to be removed
            shift++;                            // increment `shift`
        else 
            a[i - shift] = a[i];                // move i-th item `shift` positions left
    }
    for (int i = a.length - shift; i < a.length; i++)
        a[i] = null;                            // replace remaining items by nulls

    return a.length - shift;                    // return new "length"
}  
Run Code Online (Sandbox Code Playgroud)

小测试:

String[] a = {"0", "1", "2", "3", "4"};
removeItems(a, 0, 3, 4);                     // remove 0-th, 3-rd and 4-th items
System.out.println(Arrays.asList(a));        // [1, 2, null, null, null]
Run Code Online (Sandbox Code Playgroud)

在您的任务中,您可以先扫描数组以收集“a”的位置,然后调用removeItems().