我有一个包含一个对象的数组,其中包含不同的变量(矩形,图像等等)
我正在寻找一种有效的方法来保存数组,并且是一种有效的搜索方式。
我每次需要搜索其矩形在渲染范围内的所有对象
有没有一种好的,有效的,快速的方法呢?
答案 0 :(得分:2)
根据您修改“要渲染的内容”数组的频率与您尝试搜索内容的频率相比,您可能会以不同的方式查看数据。假设您只是偶尔修改数组,因此您有一些Renderable对象数组,其中每个Renderable都有一个返回矩形的getOutline():
Renderable[] arr = new Renderable[] { /* whatever */ };
加速频繁搜索的规范解决方案是根据搜索的属性对数组进行排序,然后使用O(log n)而不是O(n)的二进制搜索,就像遍历数组一样。在这种情况下,您不能这样做,因为您基本上是在2/4属性/键上编制索引:每个矩形的X范围和Y范围。
你可以做的是让四个数组由相同的对象组成(因为它们是引用,空间成本不大)并且每个数组都按相应的四个属性之一排序矩形:“顶部”(最小Y),“底部”(最大T),“左侧”(最小X)和“右侧”(最大X)。例如,您可以定义其中一个,如:
Comparator<Renderable> topComp = (r1, r2) -> r1.getOutline().top - r2.getOutline().top;
Renderable[] byTop = Arrays.stream(arr).sorted(topComp).toArray(Renderable[]::new);
// The same goes for byBottom, byLeft and byRight
中间的第一行使用lambda创建一个Comparator,该lambda对Renderable对象施加与其顶部坐标的自然顺序相同的排序。它可以被Comparator.comparingInt(r -> r.getOutline().top);
替换,因为Comparator接口具有静态方法来创建这样做的比较对象。
现在,当你有一个要绘制的区域时,你可以使用二进制搜索来快速找到哪些矩形重叠:
// We'll say that the variable "reg" contains a rectangle that needs to be redrawn
// We'll make it a fake Renderable so "it" can be searched in the arrays
Renderable rReg = new FakeRenderable(reg);
int topPos = Arrays.binarySearch(byTop, rReg, topComp);
int bottomPos = Arrays.binarySearch(byBottom, rReg, bottomComp);
// etc for leftPos and rightPos
执行4 O(log n)查找后,每个xPos变量可能是正数或负数。
iFirstGreater = -(x + 1);
其中x是binarySearch返回的值。然后,iFirstGreater
将数组分区为“小于键”和“大于键”。因此,在任何情况下,索引都会对四个数组进行分区。您有四个指向四个排序数组的索引,告诉您哪些可渲染对象在您的区域顶部上方/下方有一个“顶部”坐标,其上方/下方的“底部”低于/低于您所在区域的“底部”,左侧和右侧字段的相同位置相同。使用该信息,您可以决定每个可渲染对象是否为
答案 1 :(得分:1)
for (Rectangle rectangle : array) {
// check rectangle
}
答案 2 :(得分:0)
由于您要遍历数组中的所有元素,因此实际上没有任何内容。只需遍历所有元素并检查每个矩形:
for(int i = 0; i < myArray.length; i++) {
Rectangle r = myArray[i].rectangle;
//do something with r
}