有效删除Java中arraylist中每个数组的第一个元素

时间:2018-08-16 15:32:24

标签: java arrays arraylist out-of-memory

我想从存储在double[][]内的每个ArrayList<double[][]>数组中删除第一个元素。此列表存储了大量数据(60000个元素)。

我试图通过以下代码实现这一目标:

public ArrayList<double[][]> correctInput(ArrayList<double[][]> input) {
    double[][] temp;
    ArrayList<double[][]> correctedinput = new ArrayList<>();

    for (int n = 0; n < input.size(); n++) {
        temp = new double[input.get(0).length - 1][1];

        for (int i = input.get(n).length - 1; i > 0; i--) {
            temp[i - 1][0] = input.get(n)[i][0];
        }

        correctedinput.add(temp);
    }

    return correctedinput;
}

虽然我的代码适用于较小的列表,但是当尝试在较大的列表上使用它时,会导致

  

java.lang.OutOfMemoryError:超出了GC开销限制

可能是因为我正在为列表的每个元素重新定义双精度数组(命名为temp)。 还有一件事:列表中的数组用作向量,这就是为什么它们是2D数组的原因,尽管它们只有长度为1。

'temp [0] .lenght = 1'

问题是我如何才能使非常大的列表更有效地运行。
任何提示将不胜感激。

4 个答案:

答案 0 :(得分:2)

尝试此方法:

Java 8 +

public static <T> void remove1stArrayElementFromEveryElement(List<T[]> list) {
    list.replaceAll(array -> Arrays.copyOfRange(array, 1, array.length));
}

Java 7 +

public static <T> void remove1stArrayElementFromEveryElement(List<T[]> list) {
    for (ListIterator<T[]> iter = list.listIterator(); iter.hasNext(); ) {
        T[] array = iter.next();
        array = Arrays.copyOfRange(array, 1, array.length);
        iter.set(array);
    }
}

我已将其设为通用,因此它可以与double[][]int[][]一起使用。这是一个空方法,因为它直接修改了传递的列表,而不进行复制。它制作的唯一副本是列表中每个数组的临时副本。此外,它还适用于任何列表,而不仅限于ArrayList

答案 1 :(得分:1)

Java中的数组大小无法更改。因此,从技术上讲,您不能从数组中删除元素。基本上,您需要构造一个新数组,然后从原始数组复制。这就是你所做的。

对于复制,Arrays.copyOfRange(oldArr, 1, oldArr.length)可能是最简单的方法。尝试看看有什么变化。

我认为您在这里还有其他选择:

  1. 增加堆容量(例如-Xmx1024m)

  2. 重新考虑您输入double [] []输入吗?有什么解决方法吗?

答案 2 :(得分:1)

由于您不需要保留输入列表,并且由于您有足够的存储空间,因此该列表对您来说应该可以正常工作。无需创建新对象,只需更改当前对象即可。通过跳过第一个元素,然后设置新的元素,为每个外部数组创建一个副本。

public static void correctInputVoid(ArrayList<double[][]> input) {
    for (ListIterator<double[][]> listIterator = input.listIterator(); listIterator.hasNext(); ) {
        double[][] next = listIterator.next();
        listIterator.set(Arrays.copyOfRange(next, 1, next.length));
    }
}

答案 3 :(得分:0)

除了在具有更多RAM的计算机上运行程序之外(如果您已经为JVM提供了所有功能),可能没有解决问题的方法。

您的程序将为输入分配x字节的堆,然后为已校正的列表分配近乎x的堆。 OutOfMemoryError告诉您,JVM无法分配更多的内存,其中包括尝试释放未使用的引用分配的内存(GC工作)。

  

OutOfMemoryError Java8 SE

     

当Java虚拟机由于内存不足而无法分配对象并且垃圾回收器无法再提供更多内存时抛出。

问题是,将它们存储在输出列表中时,程序中没有未使用的引用。这意味着,运行此代码的计算机必须具有sizeOfInput * 2字节RAM,才能不运行到OutOfMemoryError

在旁注: 看到您不需要第二维,因为所有数组初始化器都将1用于第二维,因此请使用一维数组。仅此一项就可以极大地提高性能。