单线程包含(Point(x,y))功能的最快Java集合是什么?

时间:2010-06-07 17:12:22

标签: java collections points

在我的应用程序中,我需要检查2D坐标(x,y)的集合,以查看给定坐标是否在集合中,它需要尽可能快,并且只能从一个线程访问。 (这是用于碰撞检查)

有人可以帮我推动正确的方向吗?

5 个答案:

答案 0 :(得分:5)

我能想到的绝对最快的是维持这些点的二维矩阵:

//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)
}

如果您不关心有多少,只需boolean矩阵即可。很明显,如果矩阵只创建一次,这种情况就会很快,并且可能会在将点添加到集合中时更新。

简而言之,基本的集合并不是完美的(尽管HashSet会接近)。

修改

如果您找不到已经为您执行此操作的库,则可以很容易地将其调整为Set<Point>。像这样:

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>...
}

答案 1 :(得分:2)

我会使用一些Trove collections数据结构。

如果您的积分存储为几个int或几个float,则可以将它们打包为long:32位用于x-coord,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(..);

如果你有float个值,你可以做同样的事情,但你必须在long内打包浮动位。

答案 2 :(得分:1)

HashSet的。其O(1)平均值。如果你想要真正的O(1),你可以为你的对象创建一个包含对集合的引用。这样你就不能将 it 与你拥有的系列进行比较。

答案 3 :(得分:0)

与搜索相比,您多久更新一次这个集合?您应该根据它选择适当的数据结构。

Point2D实现可比,对吗?那么你最好的选择可能是TreeSet,它们速度非常快,我相信它们依赖于B +树,你可能知道它们在实际的数据库和文件系统中使用。

如果您认为您将对结构进行大量更新,请查看SkipList。它是guarentees O(log(操作))**注意这是针对您执行的所有操作,没有关于单个操作的运行时的保证)

答案 4 :(得分:-1)

您可以尝试某种排序集,例如treeset,因为您可以对其进行二进制搜索。