java-搜索已排序的矩形列表

java-搜索已排序的矩形列表,java,algorithm,search,2d,sortedlist,Java,Algorithm,Search,2d,Sortedlist,我有一个矩形列表,以通常的方式创建: List<Rectangle> rects = new ArrayList<>(); 提供所需功能的朴素方法是在列表中循环并在每个矩形上调用contains方法,但这太慢了 当程序运行时,列表将被修改,但与需要搜索列表的速率相比,修改的速率微不足道,因此需要相对缓慢初始化的算法也可以 我看过Collections.binarySearch,但不知道如何使用它。我对Java没有太多的经验,所以如果有另一个集合可以类似于列表使用,但更适

我有一个矩形列表,以通常的方式创建:

List<Rectangle> rects = new ArrayList<>();
提供所需功能的朴素方法是在列表中循环并在每个矩形上调用contains方法,但这太慢了

当程序运行时,列表将被修改,但与需要搜索列表的速率相比,修改的速率微不足道,因此需要相对缓慢初始化的算法也可以

我看过Collections.binarySearch,但不知道如何使用它。我对Java没有太多的经验,所以如果有另一个集合可以类似于列表使用,但更适合我需要的搜索类型,那就太好了(我已经阅读了关于地图和集合之类的文档,但没有认识到任何优势)

您可以创建地图

映射是关联两个值的最佳方式。您可以将“x”值与其在列表中的第一个位置相关联。然后,您只需从列表中的第一个“x”位置循环到另一个“x”

如果你在地图上找不到“x”,那么你的列表上就没有好的矩形


通过这种方式,您不会浏览所有坏的“x”条目。

您可以尝试查看流的性能。我不确定它是否足够快,但你可以测试一下

Rectangle rec = rects.stream().filter((r)->{
            return r.contains(x, y);
        }).findFirst().get();
使用<代码>映射在这里不合适,因为您没有创建键值对,
也不适合此上下文


确保覆盖
矩形中的
equals()
hashCode()
,如下所述:

您可以像这样使用并行流搜索列表

public Rectangle findContainingRectangle(final int x, final int y) {
    List<Rectangle> rectangles = new ArrayList<>();

    Rectangle rec = rectangles.parallelStream().filter((r)->{
        if(r.getX()==x && r.getY()==y){
            return true;
        }
        return false;
    }).findFirst().get();
    return rec;
}
public Rectangle find包含矩形(final int x,final int y){
列表矩形=新的ArrayList();
Rectangle=rectangles.parallelStream().filter((r)->{
if(r.getX()==x和&r.getY()==y){
返回true;
}
返回false;
}).findFirst().get();
返回记录;
}

在维护排序列表的同时,您可以在“X”坐标上使用二进制搜索来查找包含所需“X”的矩形的候选,然后在“Y”坐标上使用二进制搜索

您应该自己实现二进制搜索,我看不到可以使用Collections.binarySearch方法的方法

预期复杂度:O(logn)为n矩形的数量。 (因为您可能有重复的,所以会更详细一些)


然而,要做到这一点,您应该在添加其他实例的同时保持数组的排序,(在每次插入后排序)。

只需多次运行二进制搜索,因为同一个x的概率很低,正如您所说,不会花费很多次,所以它仍然是logn

a) 运行二进制搜索

b) 删除找到的项目-并将索引保留在找到该项目的位置

c) 对剩余列表重复a)处的二进制搜索,直到返回null

d) 然后你有一个小的索引数组,你可以看到哪一个是最小的

e) 然后在指定位置重新插入移除的元素

这似乎是一个解决方案:谢谢。我的例子有点“简单”,因为我只需要返回一个包含矩形的,但R树可能仍然是一个解决方案。
public Rectangle findContainingRectangle(final int x, final int y) {
    List<Rectangle> rectangles = new ArrayList<>();

    Rectangle rec = rectangles.parallelStream().filter((r)->{
        if(r.getX()==x && r.getY()==y){
            return true;
        }
        return false;
    }).findFirst().get();
    return rec;
}