Java 检查在矩形列表中单击哪个矩形的最快方法
我有一个矩形对象,有x,y,宽度和高度。我有一个屏幕上显示的矩形列表。我们保证它们不会重叠。给定一个用户的点击位置(x和y坐标),我想看看点击了这些矩形中的哪一个(因为它们不重叠,所以最多可以点击一个矩形) 很明显,如果用户点击了,我可以浏览所有的页面并检查每一个页面,但是这非常慢,因为屏幕上有很多页面。当我在列表中插入一个新的矩形时,我可以使用某种比较来保持矩形的排序。是否有一些方法可以使用类似于二进制搜索的方法来减少查找单击哪个rect所需的时间 注意:矩形可以是任意大小。 谢谢:)Java 检查在矩形列表中单击哪个矩形的最快方法,java,sorting,search,Java,Sorting,Search,我有一个矩形对象,有x,y,宽度和高度。我有一个屏幕上显示的矩形列表。我们保证它们不会重叠。给定一个用户的点击位置(x和y坐标),我想看看点击了这些矩形中的哪一个(因为它们不重叠,所以最多可以点击一个矩形) 很明显,如果用户点击了,我可以浏览所有的页面并检查每一个页面,但是这非常慢,因为屏幕上有很多页面。当我在列表中插入一个新的矩形时,我可以使用某种比较来保持矩形的排序。是否有一些方法可以使用类似于二进制搜索的方法来减少查找单击哪个rect所需的时间 注意:矩形可以是任意大小。 谢谢:) 编辑:
编辑:要了解我正在做什么,请访问我能想到的最快的方法肯定不是最有效的内存。这是通过利用摊销哈希表具有恒定查找时间这一事实来实现的。它会将矩形的每个点映射到该矩形。这只有在使用整数时才真正有效。如果您使用一点舍入,您可能能够让它与浮动一起工作 确保
点
类具有哈希代码和equals函数
public class PointCheck
{
public Map<Point, Rect> pointMap;
public PointCheck()
{
pointMap = new HashMap<>();
}
/**
* Map all points that contain the rectangle
* to the rectangle.
*/
public void addRect(Rect rect)
{
for(int i = rect.x; i < rect.x + rect.width; ++i)
{
for(int j = rect.y; j < rect.y + rect.height; ++i)
{
pointMap.put(new Point(i, j), rect);
}
}
}
/**
* Returns the rectangle clicked, null
* if there is no rectangle.
*/
public Rect checkClick(Point click)
{
return pointMap.get(click);
}
}
公共类点检
{
公共地图点地图;
公共点检查()
{
pointMap=newhashmap();
}
/**
*映射包含矩形的所有点
*到矩形。
*/
公共void addRect(Rect Rect)
{
对于(int i=rect.x;i
编辑:
我想我应该提到这一点:哈希映射值中的所有矩形都是对原始矩形的引用,它们不是克隆。这在很大程度上取决于您的应用程序和细节,我们还不太清楚最佳解决方案是什么。但是,据我所知,你可以制作一个指向矩形的二维数组。2D阵列将直接映射到屏幕上的像素。因此,如果将数组设为10x20,那么坐标x除以屏幕宽度乘以10(转换为int)将是第一个索引,y除以屏幕高度乘以20将是y索引。使用x和y索引,可以直接映射到它所指向的矩形。有些索引可能是空的,有些索引可能指向多个矩形(如果它们的布局不完美的话),但这似乎是我在不太了解应用程序的情况下最简单的方法。我过去在开发模拟时曾解决过一个非常类似的问题。在我的例子中,坐标是双倍的(因此不可能建立整数索引),可能需要搜索数亿个坐标 我的解决方案是创建一个
Axis
类,将每个轴表示为一系列范围。范围保证从最小值到最大值,并且当添加新范围时,该类足够聪明,可以将自己拆分为多个部分。每个范围都存储了一个通用对象。该类使用二进制搜索快速查找范围
因此,该类大致如下所示:
class Axis<T> {
public Axis(double min, double max, Supplier<T> creator);
public Stream<T> add(double from, double to);
public T get(double coord);
}
并找到一个矩形:
rectangles.get(x).get(y);
请注意,始终会存储一个对象,因此您需要一个表示形式,例如“not present”(不存在)的Rectangle.NULL
。或者您可以将其设置为可选的(尽管间接寻址会占用大量内存和处理大量矩形)
我只是在这里给出了高级设计,而不是任何实现细节,所以如果您想要更多关于如何使其工作的信息,请告诉我。在范围拆分上获得正确的逻辑并非易事。但我可以保证,即使有非常多的矩形,速度也非常快。到目前为止,您尝试过什么?你能发布一些代码吗?为什么要使用矩形?你要带多少?您的应用程序的最终目标是什么(也许您可以使用其他东西)?@tommyO,我只尝试使用未排序的数组来存储矩形,然后在用户单击时检查所有矩形。这行缺少括号:
rectanges.add(x,x+w).forEach(r->r.add(y,y+h).forEach(Rectangle::setPresent);
。
rectangles.get(x).get(y);