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

发布于 2024-09-04 05:02:55 字数 104 浏览 4 评论 0原文

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

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

In my application I need to check a collection of 2D coordinates (x,y) to see if a given coordinate is in the collection, it needs to be as fast as possible and it will only be accessed from one thread.
( It's for collision checking )

Can someone give me a push in the right direction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

凉城凉梦凉人心 2024-09-11 05:02:55

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

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

如果您不关心有多少个点,那么只需一个布尔矩阵就可以了。显然,只有在矩阵仅创建一次并且可能在将点添加到集合中时进行更新时,这才会很快。

简而言之,基本的 Collections 对此并不完美(尽管 HashSet 会很接近)。

编辑

如果您还没有找到可以为您执行此操作的库,则可以轻松将其改编为Set。像这样的事情:

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

The absolute fastest I can think of would be to maintain a 2D matrix of those points:

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

If you don't care how many there are, just a boolean matrix would work. Clearly this would only be fast if the matrix was created just once, and maybe updated as Points are added to the collection.

In short, the basic Collections aren't perfect for this (though a HashSet would come close).

Edit

This could be easily adapted to be a Set<Point> if you don't find a library that does this for you already. Something like this:

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>...
}
欢烬 2024-09-11 05:02:55

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

如果您的点存储为几个 int 或几个 float,您可以将它们打包在 long 中:x 坐标为 32 位y 坐标为 32 位。然后,您可以使用 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 值,你可以做同样的事情,但你必须打包 float long 内的位。

I would go using some Trove collections data structures.

If your points are stored as a couple of int or a couple of float you can pack them in a long: 32 bits for x-coord and 32 bits for y-coord. Then you can use a TLongHashSet that is an HashSet optimized for working with primitive data (it will be faster and consume less memory compared to normal java collections).

If you have int coordinates it would be something like

static private long computeKey(int h1, int h2)
{           
    return ((long)h1) << 32 | h2;
}

to compute the key and then use it

TLongHashSet set = new TLongHashSet()
set.add(long v);
set.addAll(long[] v);
set.containsAll(..);

if you have float values you can do the same thing, but you have to pack float bits inside the long.

冷情妓 2024-09-11 05:02:55

哈希集。其平均值为 O(1)。如果您想要真正的 O(1),您可以为您的对象创建一个包装器,该对象具有对集合的引用。这样你就不能仅仅将它与你拥有的收藏进行比较。

HashSet. Its O(1) average. If you want true O(1) you can make a wrapper for your object which has a reference to a collection. That way you cant just compare it with the collection you have.

愛上了 2024-09-11 05:02:55

与搜索集合相比,您需要多久更新一次集合?您应该基于此选择合适的数据结构。

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

如果您认为要对结构进行大量更新,请查看 SkipList。它保证 O(log(operations)) **注意,这适用于您执行的所有操作,不保证单个操作的运行时间)

How often do you have to update the collection in comparison to searching it? You should chose an appropriate data structure based on that.

Point2D implements comparable, right? Then your best bet is probably a TreeSet, they are incredibly fast and I believe they rely on B+ trees, which you may know are used in actual databases and filesystems.

If you think you're going to be doing a fair amount of updates to the structure, take a look at the SkipList. It guarentees O(log(operations)) **NOTE this is for ALL operations you do, there is no guarentee about the runtime of a single opperation)

笨笨の傻瓜 2024-09-11 05:02:55

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

You can try some sort of sorted set, like treeset, since you can do binary searches on it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文