我有一种算法&使用Java解决性能问题。我有大量的2D积分(让我们说它们大约有10万个)。我想获得一组位于搜索点SP(X_sp,Y_sp)周围的给定区域中的一组,以便我想获得符合标准的点P(x y):
x介于X_sp - constValue和X_sp + constValue之间,y介于Y_sp - constValue和Y_sp + constValue之间
为了让您了解数字关系,constValue将为2,5或10,x,y将介于0和1000之间。它意味着是一个Web服务,因此可以搜索必须同时考虑许多不同的点。
由于这些是固定点(不是因为计算或其他原因而改变),我认为提供一个按X排序的对象列表和另一个对象列表是最佳的,但是按Y排序。然后,我'首先得到X范围内的点,然后使用引用从另一个列表中获取这些点的集合(按Y排序)。然后我将这个选择缩小Y,结果得到给定区域中的点。
我从不了解Java内部,所以我想咨询最优化的方法。我应该使用哪些对象来存储排序点,以便快速搜索范围内的对象?或者我可能必须为此任务实现我的自定义算法?此外,在数据库中存储点时,SQL查询是否足够快以提供结果?或者NoSQL dbs对此更好?
我要进行自己的测试,但我正在寻找初学者。
答案 0 :(得分:1)
我可能会使用TreeMap<Integer, TreeSet<Integer>>
,其中地图的关键字是x
坐标,而对于每个x
坐标,您有一个{{1}的列表坐标。然后,您可以使用floorEntry
和ceilingEntry
查找属于您范围内的y
坐标。然后,对于您获得的每个x
集,您可以使用ceiling
和floor
来获取相应的条目。
当然,这只会给你盒子边界的坐标(四个角)。但是TreeSet<Integer>
还有subset
,它会为您提供一系列值。你必须使用它两次;一次用于TreeSet
坐标列表(您可以使用地图的x
方法获取密钥集)在您的范围内,然后对于每个keySet
坐标,{{1在边界内的坐标。所以伪代码有点像这样:
x
我还没有对此进行测试,因此可能存在一些我错过的错误或错误。让我知道,我会更正答案。
y
和List<Point> result = new ArrayList<>();
int lowerX = points.ceilingKey(x - c);
int upperX = points.floorKey(x + c);
for each x coordinate in points.entrySet().subset(lowerX, upperX)
TreeSet<Integer> yCoordinates = points.get(x);
lowerY = yCoordinates.ceiling(y - c);
upperY = yCoordinates.ceiling(y + c);
for each y coordinate in yCoordinates.subset(lowerY, upperY)
result.add(new Point(x, y))
来电是floor
我认为 - 这是您获得性能优势的地方,因为如果您使用列表,那么ceiling
就是log(n)
看起来。
注意:我不知道这是否是最高效的。通常情况下,这不是一个开放式问题的地方,所以你可能在其他地方有更多的运气。