【问题标题】:Java - What's the most efficient way of removing a set of elements from an Array[]Java - 从 Array[] 中删除一组元素的最有效方法是什么
【发布时间】:2010-04-14 15:33:09
【问题描述】:

我有这样的事情

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 的新 Object

【问题讨论】:

  • 如果您使用的是恒定大小的数组,就像您在上面一样,为什么不直接引用这些元素的索引并将它们清空。你想调整数组的大小还是简单地从中删除元素?

标签: java arrays


【解决方案1】:

您不能从Java 数组中删除元素。你可以做的是:

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

【讨论】:

    【解决方案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 可能更合适。

    【讨论】:

      【解决方案3】:

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

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

      我认为,最有效的方法(如果您仍想使用数组)是创建仅包含旧数组中必要元素的新数组:

      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 收藏集的另一种方式(我不确定它是否有效,但对我来说看起来很优雅):

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

      【讨论】:

        【解决方案4】:

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

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

        您可以做的最好的事情是使用LinkedList,它的好处是允许通过排除对象而不产生任何孔来移除对象,它们会从结构中消失。然后您可以使用Collection.toArray(..) 来获取您的新数组。

        【讨论】:

          【解决方案5】:

          如果您有要修改的数组,那么我建议使用各种 Collections 类,例如 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();
          }
          

          【讨论】:

            猜你喜欢
            • 2016-08-05
            • 1970-01-01
            • 1970-01-01
            • 2018-03-31
            • 2011-04-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多