Java 以最快的方式从整数数组中删除子数组?

Java 以最快的方式从整数数组中删除子数组?,java,arrays,Java,Arrays,在Java中,我们有一个数组int[]a=newint[10000000]用任意数字完全填充。在代码中,我们经常需要删除任意子序列:这是一组可能不连续的元素 在LinkedList上使用int[]的原因是通过元素时的速度增益。目前没有删除元素,所以在运行应用程序时会存储大量垃圾。删除元素可能会加快速度,所以这是一个非常有趣的问题 如何以尽可能快的方式从阵列中删除子项?使用[系统#阵列复制](http://docs.oracle.com/javase/1.4.2/docs/api/java/lan

在Java中,我们有一个数组
int[]a=newint[10000000]用任意数字完全填充。在代码中,我们经常需要删除任意子序列:这是一组可能不连续的元素

LinkedList
上使用
int[]
的原因是通过元素时的速度增益。目前没有删除元素,所以在运行应用程序时会存储大量垃圾。删除元素可能会加快速度,所以这是一个非常有趣的问题

如何以尽可能快的方式从阵列中删除子项?

使用[系统#阵列复制](http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/System.html#arraycopy(java.lang.Object,int,java.lang.Object,int,int))如下:

      System.arraycopy(orginalArray, startIndex, newArray, 
                     newArrayStartIndex, numOfElementsToCopy);
      orginalArray = newArray;

请注意:这适用于连续位置。如果有更多的连续部分,这仍然是有用的,并且可以以类似的方式多次调用但是如果要删除的位置是完全随机的,那么我认为您需要遍历数组。

这取决于您是否要缩短数组,或者是否可以在数组末尾允许未使用的元素。这方面的工具是。要缩短阵列,您需要分配一个新阵列:

public int[] remove(int[] original, removeStart, removeEnd) {
    int originalLen = original.length;
    int[] a = new int[originalLen - removeEnd - removeStart];
    System.arraycopy(original, 0, // from original[0]
        a, 0,                     // to a[0]
        removeStart);             // this many elements
    System.arraycopy(original, removeEnd, // from original[removeEnd]
        a, removeStart,                   // to a[removeStart]
        originalLen - removeEnd);         // this many elements
    return a;
}
要仅压缩阵列,请执行以下操作:

System.arraycopy(array, removeEnd, // from array[removeEnd]
    array, removeStart,            // to array[removeStart]
    array.length - removeEnd);     // this number of elements
你不必担心重叠的范围<代码>阵列复制
正确处理这些问题

如果要删除的元素范围不连续,则可以泛化其中一个解决方案(移动的内容更少,但代码更复杂),或者可以单独删除每个连续块(编程更容易,但移动的数据将被丢弃)

如果你有散乱的索引要删除,我会手动删除。设计取决于它是分散的单个索引还是范围的集合。对于后者(这是未经测试的,但它应该给你一个想法):

/**
*简单的类来保持范围的开始和结束。
*/
公共静态类范围实现可比较{
int启动;
内端;
公共整数比较(范围其他){
if(startother.start)返回1;
if(endother.end)返回1;
返回0;
}
}
/**
*从数组中删除范围列表。
*@param original要从中删除值的数组。
*@param删除要删除的范围列表。这一定是
*在调用此方法之前,按范围开始的升序排序。
*@param compact标志,指示是否仅压缩原始文件
*数组或将值复制到新数组中。如果为false,将分配
*包含未删除元素所需的精确大小的新数组。
*/
公共int[]删除(int[]原始,列表删除,布尔压缩){
int[]a;
if(紧凑型){
a=原件;
}否则{
int len=0;
for(Range-Range:toRemove)len+=Range.end-Range.start;
a=新整数[原始长度-len];
}
int nextSource=0;
int nextDest=0;
用于(范围:toRemove){
if(nextSource
使用
int[]
而不是
LinkedList
(或
ArrayList
,这将是比
LinkedList
更好的选择)的另一个(可能更重要)原因是,它避免了将每个值装箱到
整数中的开销。在某些情况下,这种自动装箱/取消装箱可能是一个巨大的垃圾源,会显著影响代码的性能。
/**
 * Simple class to hold the start and end of a range.
 */
public static class Range implements Comparable<Range> {
    int start;
    int end;
    public int compareTo(Range other) {
        if (start < other.start) return -1;
        if (start > other.start) return 1;
        if (end < other.end) return -1;
        if (end > other.end) return 1;
        return 0;
    }
}
/**
 * Remove a list of ranges from an array.
 * @param original the array from which to remove the values.
 * @param toRemove the list of ranges to remove. This must be
 *    sorted in ascending order of range start before calling this method.
 * @param compact flag indicating whether to simply compact the original
 *    array or to copy the values into a new array. If false, will allocate
 *    a new array of the exact size needed to contain the elements not removed.
 */
public int[] remove(int[] original, List<Range> toRemove, boolean compact) {
    int[] a;
    if (compact) {
        a = original;
    } else {
        int len = 0;
        for (Range range : toRemove) len += range.end - range.start;
        a = new int[original.length - len];
    }
    int nextSource = 0;
    int nextDest = 0;
    for (Range range : toRemove) {
        if (nextSource < range.start) {
            System.arraycopy(original, nextSource, a, nextDest,
                range.start - nextSource);
            nextDest += range.start - nextSource;
            nextSource = range.start;
        }
        nextSource = range.end;
    }
    if (nextSource < original.length) {
        System.arraycopy(original, nextSource, a, nextDest,
            original.length - nextSource);
    }
    return a;
}