【问题标题】:Java Array EfficiencyJava 数组效率
【发布时间】:2013-03-13 05:16:09
【问题描述】:

我不能 100% 确定这种机制的作用,所以我决定在这里发帖以进一步澄清。

我正在做一个应该用 Java 处理大量数据的项目(它必须是 Java)。我希望它尽可能高效。我所说的高效是指内存和速度计算应该放在第一位,而可读性应该放在第二位。

现在我有两种方法来存储我的数据:创建一个 MyObject 数组

1) MyObject[][] V = new MyObject[m][n]

或者创建两个int数组:

2) int[][] V = new int[m][n]

3) int[][] P = new int[m][n]

显然MyObject 至少包含两个字段和一些方法。现在我注意到,在循环MyObject 数组以分配值时,我必须调用new,否则我会得到一个空指针异常。这意味着第 1 行中的 new 不够用。考虑到数组也是 Java 中的对象,这是否比 P[i][j]=n 更昂贵的操作?

【问题讨论】:

  • 我认为是的 v[i][j] = new MyObject(object1 , object2);比 P[i][j]=n 贵; .但我认为你不必对此如此认真。
  • 开始编码之前搞清楚不同内存布局的效率永远不会奏效。您应该以两种方式之一对其进行编码,无论哪种方式,然后配置文件。如果太慢,看看是什么让你慢了下来;很有可能,它与内存中对象的布局无关。
  • 相关,如果 n 明显大于或小于 m:stackoverflow.com/questions/15339296/…
  • 更新:我没有做任何空间分析,但我的代码运行速度是数组的两倍,所以我会坚持下去。

标签: java multidimensional-array performance memory-efficient


【解决方案1】:

为了快速处理真正海量的数据,最好将数据放置在单个连续的内存块中,以便您一起访问的数据彼此靠近。这应该最大限度地减少缓存未命中,这是当今最糟糕的性能杀手之一。

在 java 中,您可以通过仅使用一个单一的一维基元数组来实现这一点。如果您使用两个数组甚至二维数组,则不再保证数据位于一个连续的块中。

另一个稍微复杂的解决方案是使用堆外数据结构,如下所示:http://mechanical-sympathy.blogspot.com/2012/10/compact-off-heap-structurestuples-in.html

【讨论】:

    【解决方案2】:

    考虑到数组也是 Java 中的对象,这是一个比 P[i][j]=n 更昂贵的操作吗?

    在第一种情况下,您创建一个数组对象,用于存储数组类型的其他对象。数组对象和要存储在数组中的对象都需要实例化,这意味着您将需要 m * n + 1 对象实例化以及 (m * n + 1) * objectSize 内存消耗。

    在第二种情况下,您只需实例化数组对象; int 原语不是对象,所以这应该更快,内存效率也更高,因为对象内存大小比 int 大几倍。在这里,您基本上有 1 个对象实例化和(m * n) * intSize + objectSize 内存消耗。

    使用原语的另一个原因是,当用作局部变量时,它们被保存在堆栈中。在将计算值存储在数组中之前,您可能会在方法中使用中间局部变量,并且这些变量的内存分配/释放时间是堆上对象的数倍。

    【讨论】:

    • 对象内存消耗真的比两个原语大得多吗?根据我的理解,为对象分配的空间将由它的两个原始字段和一些开销组成。这是根据javamex.com/tutorials/memory/object_memory_usage.shtml为什么会“几倍”大?
    • @user2002121 Integer 对象占用的空间是原来的四倍;一个 Object 预计会占用三倍以上的空间(因为它没有 int) - 请参阅可靠的参考:ibm.com/developerworks/java/library/j-codetoheap/index.html 还要注意的是,他不能将 Object 对象用于任何事情(例外是同步锁是在这种情况下不是)。
    【解决方案3】:

    我经常通过分析发现,用几个标量数组替换一个对象数组可以提高内存消耗和性能。

    但是,只有分析才能判断在您的情况下它是否值得优化。

    一个好的分析器可以让您测量代码的性能和内存占用。

    【讨论】:

      【解决方案4】:

      首先,您必须使用 List 或 Set,即 java 中的集合而不是数组。因为您可能不知道需要处理的数据大小。此外,集合具有 API 方法,可让您轻松执行操作,例如插入元素或删除元素。使用数组非常复杂且容易出错,因为您可能需要一次又一次地对其进行迭代,而且大小必须在编译时确定,如果您有可变大小的数据,这是不可能的。

      此外,在运行时分配内存(即使用 new 关键字)非常昂贵,然后只需将值分配给已经存在的对象,即 p[i][j]=v;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-28
        • 1970-01-01
        • 2013-03-25
        • 1970-01-01
        • 2012-05-27
        • 1970-01-01
        • 2011-01-19
        相关资源
        最近更新 更多