我有一组房间和通道,我可以将其转换为矩形(x,y,宽度,高度)或点(x,y)列表。 Room
和Passage
都扩展了Pointable
接口。对于Room类,实现了getPoints()方法为
public Set<Point> getPoints() {
Set<Point> array = new HashSet<Point>();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
array.add(new Point(x + i, y + j));
}
}
return array;
}
问题:
我必须确定给定Pointable
所属的Point
。没有房间相交。我最初使用HashMap<Point,Pointable>
将每个Point
与Pointable
相关联,后者能够在O(n)时间内快速访问答案。但是,现在有必要在生成级别时多次重新计算HashMap
。
此时,使用HashMap(考虑到生成和访问)还是应该使用其他方法(例如一组二维间隔树)是否更有效?
答案 0 :(得分:1)
此时,使用HashMap(考虑到生成和访问)还是应该使用其他方法(例如一组二维区间树)是否更有效?
除了进行测量的人之外,没人知道。这一切都取决于您需要更新数据的频率,更改的频率以及查询的频率。
还有Room
的大小。有几点,HashMap
在一个典型场景中胜出,其中有数千个,更新积分的开销占主导地位。
你不能为所有Point
使用数组吗?如果是这样,那么它肯定会比HashMap
更快,特别是对于更新(除非它真的很大)。
这可能有用也可能没用。
实际上,不仅每个Room
都有Point
个,而且每个Point
可能只有一个Room
(n:1)。如何实施,这是一个不同的问题。
鉴于此,我们遇到了一个标准问题:如果您双向链接,则必须保持两个链接同步。最简单的解决方案是使setter(“adders”/“removers”)尽可能私有,只从方法中调用它们
void link(Room room, Point point) {
Room oldRoom = point.getRoom();
if (oldRoom!=null) oldRoom.removePoint(point);
room.addPoint(point);
point.setRoom(room);
}
您从Point
到Room
的链接是外部的,但这几乎不会改变任何内容(除了保持Point
更小,可能更清晰,并为每次访问添加HashMap的微小开销)
它通常也是最快的,因为通常会有更多的查询而不是更新。您的问题是更新费用按Room
大小按比例放大。 如果没有您告诉我们某些数据,则无法估算。
由于太多的点和房间尺寸变化太大,您可以将点坐标舍入到某个n
的倍数,并保持一个数组,其中包含与网格相交的所有房间的集合。您可以像以前一样继续进行,但是更新开销会降低几乎由房间区域(*)给出的因素和搜索开销更高,因为您必须从集合中选择真正匹配的房间(如果有的话)。
(*)对于未与网格对齐的房间,交叉矩形的数量明显更高。