Java - 从Array []中删除一组元素的最有效方法是什么

时间:2010-04-14 15:33:10

标签: java arrays

我有类似的东西

Object[] myObjects = ...(initialized in some way)...
int[] elemToRemove = new int[]{3,4,6,8,...}

从myObjects中删除索引位置3,4,6,8的元素的最有效方法是什么?

我想用像

这样的签名实现一个有效的效用方法

public Object[] removeElements(Object[] object, int[] elementsToRemove) {...}

返回的Object []应该是一个大小为myObjects.length的新对象 - elemToRemove.length

5 个答案:

答案 0 :(得分:3)

您无法从Java数组中删除元素。你能做的是:

  • 创建一个只有的数组 你想要保留的元素。
  • 请改用Collections

答案 1 :(得分:2)

您需要创建一个新数组,因为数组的大小不会改变(在保持相同数组时不能“移除”元素,它会在某处创建漏洞)。我建议这个:

Object[] nobjs = Arrays.copyOf(myObjects, myObjects.length - elemToRemove.length);
for (int i = 0, j = 0, k = 0; i < myObjects.length; i ++) {
    if (j < elemToRemove.length && i == elemToRemove[j]) {
        j ++;
    } else {
        nobjs[k ++] = myObjects[i];
    }
}

这假定elemToRemove已经排序,没有重复,并且只包含在源数组中有效的索引。 Arrays.copyOf()调用仅用于确保新数组的运行时类型与源数组的运行时类型相同。

如果您经常需要从数组中“删除”数据,因此需要创建新数组,那么Java数组可能不是最有效的数据结构。 LinkedListArrayList可能更合适。

答案 2 :(得分:1)

如果你想频繁删除它的元素,我建议你使用LinkedList而不是数组。

使用数组(array-&gt;链表 - &gt;删除元素 - >数组)实现它也很容易,但效率不高:

我认为,最有效的方法(如果你仍然想使用数组)是创建只有旧数组中必需元素的新数组:

Object[] filteredObjects = new Object[myObjects.length - elemToRemove.length];
int j = 0;
for (int i = 0; i < myObjects.length; i++) {
   if (!shouldRemove(i)) {
      filteredObjects[j++] = myObjects[i];
   }
}
myObjects = filteredObjects;

我没有展示shouldRemove。我认为你应该创建一组索引而不是elemToRemove数组(索引是唯一的,所以它在任何情况下都是首选方式)。然后shouldRemove可以更改为elemToRemove.contains(i)


可以建议您使用Google Collections的另一种方式(我不确定它是否有效但对我来说看起来很优雅):

for (int index : elemToRemove) {
    myObjects[i] = null;
}
myObjects = Collections2.filter(Arrays.asList(myObjects), new Predicate<Object>() {
    @Override
    public boolean apply(Object obj) {
        return obj!= null;
    }
}).toArray();

答案 3 :(得分:1)

Java数组是不可变的,你不能只是删除项目而不会在中间留下漏洞。

你可以做的是首先删除所有元素的出现,然后通过填充所有孔来压缩阵列;顺便说一句,这是非常低效的。否则,您可以为正确的元素创建一个新数组,但是您需要先知道它的大小..

你能做的最好的事情就是使用一个LinkedList,它可以通过排除物体而不产生任何洞来移除物体,它们只是从结构中消失。然后,您可以使用Collection.toArray(..)获取新阵列。

答案 4 :(得分:0)

如果您有要修改的阵列,那么我建议使用各种集合类,例如LinkedListArrayList。常规数组无法调整大小,因此您不能简单地添加/删除元素。

但是,假设您有两个数组Object[] myObjectsObject[] toRemove,并且您需要一个函数返回一个新数组,其中toRemove中的元素从myObjects中删除:

public static Object[] remove(Object[] myObjects, Object[] toRemove)
{
    HashSet<Object> tr = new HashSet<Object>();
    tr.addAll( Arrays.asList(toRemove) );
    List<Object> removed = new ArrayList<Object>();
    for(Object o : myObjects)
        if( !tr.contains(o) )
            removed.add(o);
    return removed.toArray();
}