简体   繁体   English

将 double[] 转换为不可变列表的成本更低的方法

[英]Less expensive way of converting a double[] to an immutable list

I want to convert an array double[] to an immutable collection for use in a value object.我想将数组double[]转换为不可变集合,以便在值 object 中使用。 However, I am dealing with a very large array and I keep getting the error java.lang.OutOfMemoryError: Java heap space .但是,我正在处理一个非常大的数组,并且不断收到错误java.lang.OutOfMemoryError: Java heap space

I am currently using我目前正在使用

Collections.unmodifiableList(DoubleStream.of(myArray).boxed().collect(Collectors.toList()));

I think it is because of this my program is running out of memory.我认为这是因为我的程序用完了 memory。 Is there a cheaper way to convert double[] to an immutable list?有没有更便宜的方法可以将 double[] 转换为不可变列表?

How about creating your own List<Double> ?创建自己的List<Double>怎么样? If you implement AbstractList<Double> , you'd only need to implement two methods for an unmodifiable list:如果您实现AbstractList<Double> ,您只需要为不可修改的列表实现两种方法:

class MyDoubleList extends AbstractList<Double> implements RandomAccess {

    private double[] backingArray;

    public MyDoubleList(double[] backingArray) {
        this.backingArray = backingArray;
    }

    @Override
    public Double get(int index) {
        return backingArray[index];
    }

    @Override
    public int size() {
        return backingArray.length;
    }

    // adding other list methods should be trivial...
}

Usage:用法:

List<Double> list = new MyDoubleList(myBigDoubleArray);

Note that if you change the backing array, the list contents will change as well.请注意,如果更改后备数组,列表内容也会更改。 To prevent this, you'd usually copy the array passed in, but since copying the array will probably cause an out of memory exception, I didn't do it.为了防止这种情况,您通常会复制传入的数组,但由于复制数组可能会导致 out of memory 异常,所以我没有这样做。


Or if you use Guava, use Doubles.asList(myBigDoubleArray) , which does essentially the same thing.或者,如果您使用 Guava,请使用Doubles.asList(myBigDoubleArray) ,它的作用基本相同。 Thanks to Joe for the suggestion!感谢乔的建议!

Streams are great for functional programming, and readability but should be avoided when performance is the main concern.流非常适合函数式编程和可读性,但当性能是主要问题时应避免使用。 They create unnecessary extra objects.他们创建了不必要的额外对象。

Also surprisingly, arrays of the double primitive types consume more memory than their wrapper class Double arrays (ref: https://www.baeldung.com/java-primitives-vs-objects ) Also surprisingly, arrays of the double primitive types consume more memory than their wrapper class Double arrays (ref: https://www.baeldung.com/java-primitives-vs-objects )

Use a Double object array instead of a double primitive, and then run:使用Double object 数组而不是双原语,然后运行:

Collection<Double> l = Collections.unmodifiableCollection(Arrays.asList(myArray));

I compared the 2 approaches like this我比较了这两种方法

    public static void main(String[] args) {
        int len = 1000000;
        Double[] myArray = new Double[len];
        for (int i = 0; i < len; i++) {
            myArray[i] = Math.random();
        }
        Collection<Double> l = Collections.unmodifiableCollection(Arrays.asList(myArray));
        long totalMem = Runtime.getRuntime().totalMemory();
        long usedMem =  totalMem - Runtime.getRuntime().freeMemory();
        System.out.println("totalMem="+humanReadableByteCountBin(totalMem));
        System.out.println("usedMem=" + humanReadableByteCountBin(usedMem));
        System.out.println("l has " + l.size() + " items ");
    }

The stream approach used 48Mb, whereas Arrays.asList with Double uses 28Mb. stream 方法使用 48Mb,而Arrays.asList使用 Double 使用 28Mb。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM