在我的应用程序中,我需要检查一个二维坐标集合(x,y),以查看给定的坐标是否在集合中,它需要尽可能快,并且只会从一个线程访问。(这是为了进行碰撞检测)
有人能给我指点一下方向吗?
有人能给我指点一下方向吗?
我能想到的最快方法是维护一个二维矩阵来存储这些点:
//just once
int[][] occurrences = new int[X_MAX][Y_MAX];
for (Point p : points ) {
occurrences[p.x][p.y]++;
}
//sometime later
if ( occurrences[x][y] != 0 ) {
//contains Point(x, y)
}
public class PointSet implements Set<Point> {
private final boolean[][] data;
public PointSet(int xSize, int ySize) {
data = new boolean[xSize][ySize];
}
@Override
public boolean add(Point e) {
boolean hadIt = data[e.x][e.y];
data[e.x][e.y] = true;
return hadIt;
}
@Override
public boolean contains(Object o) {
Point p = (Point) o;
return data[p.x][p.y];
}
//...other methods of Set<Point>...
}
int
或一对float
,您可以将它们打包在一个long
中:32位用于x坐标,32位用于y坐标。然后,您可以使用TLongHashSet
,它是针对原始数据优化的HashSet
(与普通java集合相比,它会更快并且占用更少的内存)。int
坐标,那么它可能是这样的。static private long computeKey(int h1, int h2)
{
return ((long)h1) << 32 | h2;
}
TLongHashSet set = new TLongHashSet()
set.add(long v);
set.addAll(long[] v);
set.containsAll(..);
TLongHashSet
使用的哈希策略。默认使用 return ((int)(value ^ (value >>> 32))) * 31;
,这对于随机分布的数据很好,但对于像这样的数据则很糟糕。例如,像 (0,1) 和 (1,0) 这样简单的数据将导致哈希冲突。对于长整型而言,第一个32位与最后32位有相关性的情况也不适用。 - Mark PetersHashSet。它的平均时间复杂度为O(1)。如果你想要真正的O(1),你可以为你的对象创建一个包装器,该包装器具有对集合的引用。这样你就不能仅仅将它与你拥有的集合进行比较。
相对于搜索,您需要多频繁地更新集合?您应该根据此选择适当的数据结构。
Point2D实现了可比性,对吧?那么您最好选择TreeSet,它们非常快速,我相信它们依赖于B+树,您可能知道它们用于实际数据库和文件系统。
如果您认为您将会对结构进行相当数量的更新,请查看SkipList。它保证O(log(operations)) **请注意,这是您执行的所有操作,没有关于单个操作的运行时间的保证)
HashSet
可能是最好的选择。 - VeeArr