列表<双>使用 double[] 的 RAM?

发布于 2024-12-22 09:21:22 字数 1440 浏览 2 评论 0原文

Java 专家强调避免过早优化并专注于干净的 OO 设计的重要性。我试图在重写使用大量长元素(几百万)的程序的背景下协调这一原则。看起来使用 ArrayList 会消耗原始长整型数组内存的大约 3 倍,并且浪费这么多 RAM 对我来说似乎是一个合理的担忧。

我基于我使用 MemoryTestBench 类此处描述的所做的实验。我的测试和输出如下:

package memory;

import java.util.ArrayList;
import java.util.List;

public class ArrayListExperiment {

public static void main(String[] args) {

    ObjectFactory arrayList = new ObjectFactory() {
        public Object makeObject() {
            List<Long> temp = new ArrayList<Long>(1000);
            for (long i=0; i<1000; i++)
                temp.add(i);
            return temp;
        }
    };

    ObjectFactory primitiveArray = new ObjectFactory() {
        public Object makeObject() {
            long[] temp = new long[1000];
            for (int i=0; i<1000; i++)
                temp[i] = i;
            return temp;
        }
    };

    MemoryTestBench memoryTester = new MemoryTestBench();
    memoryTester.showMemoryUsage(primitiveArray);
    memoryTester.showMemoryUsage(arrayList);
}
}

和输出:

memory.ArrayListExperiment$2 produced [J which took 8016 bytes
memory.ArrayListExperiment$1 produced java.util.ArrayList which took 24968 bytes

我的问题是:我怎样才能获得 OO List 的好处,同时仍然保留原始数组的小内存占用?我认为 guava 可能会提供答案,但是浏览一下 API,我并不清楚使用哪个类来代替 ArrayList。

感谢您的任何建议。

Java experts emphasize the importance of avoiding premature optimization, and focusing instead on clean OO design. I am trying to reconcile this principle in the context of rewriting a program that uses a large array of long elements (a few million). It seems that using an ArrayList would consume about 3x the memory of a primitive array of longs, and wasting that much RAM seems like a legitimate concern to me.

I am basing this off an experiment I did using MemoryTestBench class described here. My test and output are as follows:

package memory;

import java.util.ArrayList;
import java.util.List;

public class ArrayListExperiment {

public static void main(String[] args) {

    ObjectFactory arrayList = new ObjectFactory() {
        public Object makeObject() {
            List<Long> temp = new ArrayList<Long>(1000);
            for (long i=0; i<1000; i++)
                temp.add(i);
            return temp;
        }
    };

    ObjectFactory primitiveArray = new ObjectFactory() {
        public Object makeObject() {
            long[] temp = new long[1000];
            for (int i=0; i<1000; i++)
                temp[i] = i;
            return temp;
        }
    };

    MemoryTestBench memoryTester = new MemoryTestBench();
    memoryTester.showMemoryUsage(primitiveArray);
    memoryTester.showMemoryUsage(arrayList);
}
}

and output:

memory.ArrayListExperiment$2 produced [J which took 8016 bytes
memory.ArrayListExperiment$1 produced java.util.ArrayList which took 24968 bytes

My question is: How can I reap the benefits of an OO List and still retain the small memory footprint of a primitive array? I think guava might provide the answer, but glancing through the API it's not obvious to me which class to use in place of ArrayList.

Thanks for any suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我不吻晚风 2024-12-29 09:21:22

我认为您在 Guava 中寻找的是 双打.asList

I think what you looking for in Guava is Doubles.asList

旧时光的容颜 2024-12-29 09:21:22

您可以考虑使用 Trove,它提供对原始集合的支持,例如 TDoubleArrayList 班级:

可调整大小、支持数组的双基元列表。

编辑:这个类确实没有实现List,但这就是Java避免装箱基元的代价。 Guava 的解决方案是最通用的,而 Trove 最适合更极端的性能要求。

You might consider using Trove, which provides support for primitive collections, for example the TDoubleArrayList class:

A resizable, array-backed list of double primitives.

Edit: It's true that this class doesn't implement List, but that's Java's price of avoiding boxed primitives. Guava's solution is the most versatile, while Trove is best for more extreme performance requirements.

蓝天 2024-12-29 09:21:22

我认为您正在寻找 FastUtil DoubleArrayList - 它由原始数组支持。

如果您的集合确实很大(大于 2^31 个元素),您可能还想查看它们的 BigArrays

I think you are looking for FastUtil's DoubleArrayList - it's backed by a primitive array.

If your collection is REALLY big (larger than 2^31 elements) you may also want to look at their BigArrays

鲸落 2024-12-29 09:21:22

编写您自己的使用基元数组的 ArrayList 实现。复制当前的 ArrayList 代码并将内部 Object[] 替换为 double[]。

应该是一个非常直接的复制和替换。

编辑:内存消耗的最大危险将是“增长”。它会暂时占用至少两倍的空间,再加上您种植的额外空间。如果您无法预先调整数组大小来避免这种情况,您可能需要考虑一种稍微不同的实现,该实现使用多个数组,因为它会随着时间的推移而增长。关于插入和索引的更多数学知识,但应该不会太糟糕。

Write your own implementation of ArrayList that uses an array of primitives. Copy the current ArrayList code and replace the internal Object[] with a double[].

Should be a pretty straight foward copy and replace.

EDIT: Biggest danger to memory consumption is going to be the "grow". It will briefly take up at least twice the space, plus the additional room you grow. If you can't pre-size the array to avoid this, you may want to consider a slightly different implementation that uses multiple arrays as it grows over time. A bit more math on inserting and indexing, but shouldn't be tooooo bad.

来世叙缘 2024-12-29 09:21:22

数组。 asList(T...) 可能就是您正在寻找的。它返回一个由传递给它的数组支持的 List 实例。

Arrays.asList(T...) may be what you're looking for. It returns an instance of List<T> backed by the array passed to it.

咆哮 2024-12-29 09:21:22

这是一个很好的问题——性能与代码整洁度。我认为您有理由不那么关心干净的面向对象设计,而只专注于为处理大量多头数组的特定问题创建一个好的解决方案。如果这样做,将面向性能的代码保留在一个类/包中将最大限度地减少其对整体设计的影响。假设管理大量的多头列表只是更大应用程序的一小部分......

It's a good question - performance vs code-cleanliness. I think you have grounds to be less concerned about clean OO design and simply focus on creating a good solution to the specific problem of working with a large array of longs. If you do so, keeping the performance-oriented code in one class/package will minimise its impact on overall design. Assumedly managing the large list of longs is only a small part of a bigger application...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文