针对此存储数据运行测试的最有效方法

时间:2016-08-19 13:09:01

标签: java

对于没有太多信息的标题感到抱歉,我无法想到更好的事情。当我说效率时,我的意思是代码不是cpu密集的。

问题: 想象一下用块制成的3D宇宙飞船,就像在我的世界中建造一样。我想将这个形状中的每个块的位置存储在一个自制的Ship类中。

为此,我在Ship类中使用了private List<ShipBlock> shipBlocks;。这里的ShipBlock是一个自制的类,它以向量Vec3(int x, int y, int z)的形式保存一个位置,以及与此问题无关的一些其他信息。

但现在我想在船上进行测试。船在某个testPosition(x,y,z)上包含ShipBlock,如果是,则为此返回ShipBlock。然而,我没有找到有效地做到这一点的方法。循环整个列表并测试每个位置对抗测试位置是相当昂贵的,我希望它能够快速。

相反,我决定制作一个Map<Vec3, ShipBlock> shipBlocksMap来存储信息。钥匙将是ShipBlock的位置。我可以简单地做shipBlocksMap.get(testPosition),如果船在该位置有一个ShipBlock,它将返回正确的ShipBlock。如果不是,它将返回null。

这似乎正是我想要的,直到我移动船并且所有ShipBlock都有新的位置。我在这里了解到,如果您作为关键字提供的对象发生变化,地图中的关键字就不会改变。因此,如果我现在使用shipBlocksMap.get(testPosition)使用移动船舶中的位置,它将返回null,因为关键字仍然是旧位置。 (对不起,如果它令人困惑,我不确定如何更好地解释它)

问题: 我在这里问的问题是:假如这艘船可以包含数以万计的ShipBlocks,那么测试它是否包含具有特定位置的ShipBlock的最有效方法是什么。我应该以什么方式存储船舶的船闸,以便有效地进行检查?

代码: 任何人都希望在这里看到它是Ship和ShipBlock类的代码。

public class ShipBlock 
{
    public Vec3 position;
    public String shipBlockType;

    public ShipBlock(Vec3 position, String shipBlockType)
    {
        this.position= position;
        this.shipBlockType = shipBlockType;
    }
}

public class Ship 
{
    private Map<Vec3, ShipBlock> shipBlocksMap;

    public Ship(Map<Vec3, ShipBlock> shipBlocksMap)
    {
        this.shipBlocksMap = shipBlocksMap;
    }

    public ShipBlock containsShipBlock(Vec3 position)
    {
        return shipBlocksMap.get(position);
    }
}

2 个答案:

答案 0 :(得分:4)

我认为最重要的设计变化是将块的位置相对保存到船的位置。

这样,您不需要在船舶移动时更改块的键,并且可以轻松地使用Map<Vec3, ShipBlock> shipBlocksMap进行恒定时间测试,其中键是相对位置。 您可以通过计算(概念上)relative_block_pos = absolute_block_pos - ship_pos获得相对位置。

这意味着您需要存储船舶的位置。 作为一种选择,您可以简单地选择船舶的第一个区块作为船舶的位置,因此第一个区块始终具有坐标(0, 0, 0)

这样,将所有块的坐标更改为最小值(但在大多数情况下应该不需要)。

答案 1 :(得分:0)

空间分区树可能是您的最佳选择;见space-partitioning trees。您的模型世界的一半可能是空的,并且在许多这些结构中,单个测试将揭示这一点,并且可能有助于未来的测试,直到宇宙的一半以某种方式发生变化。你有责任保持结构,但听起来结构的变化超过了测试。另一种方法可能是使用元球或Voronoi船体围绕块或块集群,以便您可以将每个测试量减少到单个测试中。