【问题标题】:Is there an alternate way to handle large 2D arrays in Java, given a memory constraint?在给定内存限制的情况下,是否有另一种方法可以在 Java 中处理大型 2D 数组?
【发布时间】:2019-01-03 03:43:32
【问题描述】:

我正在尝试使用 Java 中的 2D int 数组来实现 2D 坐标系。我有 256MB 的内存限制,并且 2D 网格足够大,内存需求可以超过这个限制。是否有另一种数据结构可以做到这一点,同时消耗更少的内存?

(编辑:目的是通过为至少访问过一次的坐标设置标志来跟踪网格内的移动。)

【问题讨论】:

  • 试试java.nio.Buffer
  • 仅将部分保存在您当前正在使用的内存中(即视口或类似的东西)并将其余部分保存在存储中
  • 这真的取决于你实际使用该数组做什么。您能否详细说明将哪种数据写入其中(也许您不需要完整的 32 位 int 类型),如何写入它(也许您不需要完全分配的数组,但可以使用动态映射,因为无论如何大多数索引仍然是空的),您如何从中读取(也许您可以将整个内容存储在某个地方,并且总是像其他人建议的那样加载一个特定的块来使用),以及任何其他可能有用的信息能够帮助你。
  • @MaxVollmer 我正在尝试跟踪您可以说的运动。每当访问 2D 网格上的某个点时,程序都会在这些坐标处设置一个标志,这样如果再次访问同一点,该标志就可以说明这一点。我可以使用boolean 数组,因为它只是一个真/假的东西,但即使这样也无助于内存问题。
  • 请使用该信息更新您的问题。

标签: java arrays optimization multidimensional-array data-structures


【解决方案1】:

您根本不需要数组。您现在正在为每个点浪费内存,而实际上您只需要存储访问点的坐标。使用一组点只存储已经访问过的坐标,并检查该组是否包含坐标以查看之前是否访问过一个点。

所以不是:

int[][] array = new int[width][height];

array[x][y] = true;

if (array[x][y] == true) {...}

你有类似的东西:

class Point
{
    public int x;
    public int y;
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
    @Override
    public boolean equals(Object o)
    {
        return o instanceof Point && this.x == ((Point)o).x && this.y == ((Point)o).y;
    }
    @Override
    public int hashCode()
    {
        return Integer.valueOf(x).hashCode() ^ Integer.valueOf(y).hashCode();
    }
}

Set<Point> set = new HashSet<Point>();

if (set.contains(new Point(x, y))) {...}

set.add(new Point(x,y));

您也可以使用地图:

HashMap<Integer, HashSet<Integer>> map = new HashMap<>();

if (map.contains(x) && map.get(x).contains(y)) {...}

if (!map.contains(x)) {
    map.add(x, new HashSet<Integer>());
}
map.get(x).add(y);

更多优化选项

如果您知道您的应用程序将访问所有点或至少一半以上的点,您可以在访问点达到 50% 时切换逻辑。基本上(伪代码):

if (pointsVisited < numAllPoints / 2)
    values in map or set are visited
else
    values in map or set are **not** visited (all others are)

您当然需要一些在达到阈值时实际执行交换的方法,从您的地图或集合中删除所有点并添加之前没有的所有点。之后,您无需添加点,而是在访问点时删除它们。

这样,在任何给定时间最多存储一半的点。

【讨论】:

  • 是的,这更有意义。我曾想过使用另一种方法来仅存储访问点的坐标(正如您所解释的),但即便如此,我还是使用了一个二维数组,并通过数组中已经存在的所有条目搜索每个新条目(看看它是否已经存在,因此被访问过)。这只会产生巨大的计算开销并减慢整个过程。毫无疑问,这是一种更好的方法。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 2010-11-17
  • 2014-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多