【问题标题】:class/object to generate unique id's生成唯一 ID 的类/对象
【发布时间】:2012-08-31 13:47:06
【问题描述】:

我使用的是 C#,但即使你不知道,也应该很容易理解这个问题。

这是我的问题:我想将一些对象保存在类似哈希集的数据结构中,以便根据int ID 查找它们。这些对象具有可变属性,因此不能对它们进行散列(我需要一些关于它们的常量来散列,是吗?)。

我所做的是开发如下界面:

public interface IUniqueIDCollection
{
    // Can return any int that hasn't been requested yet.
    public int RequestUniqueID();

    // Undos the requesting of an int
    public int ReleaseUniqueID(int uniqueID);
}

我最初的想法是在IUniqueIDCollection 中存储一个内部计数器,该计数器会随着 ID 的请求而增加。但是,一旦 ID 被释放,我将不得不跟踪已删除的范围或单个 ID。我认为后者会更好。但是,如果我使用计数器(或任何循环函数)来生成 ID,我将不得不检查已连续请求的 ID 序列,一旦计数器回绕,则未释放。

启发式方法如下:假设一次最多请求 5,000 个 ID。但是,ID 通常会请求然后发布。释放往往会在范围内发生 - 即,可能会一次请求全部 100 个,然后在很短的时间间隔内释放所有 100 个。

我知道我可以使用 GUID 或其他东西代替 int,但我想节省 ID 的空间/带宽/处理时间。

所以我的问题是:考虑到启发式方法,就伪代码而言,我上面给出的接口中的请求和释放方法应该是什么样的?

【问题讨论】:

    标签: algorithm data-structures random


    【解决方案1】:

    在几乎所有情况下,这可能比上面的Tom Panning's 更糟糕,但您可以使用 BitArray 来跟踪正在使用的 ID。内存使用量与您拥有实时 ID 的总位数一样多;最坏的情况是 512MB 用于映射所有 32 位整数。释放很简单:只需将相应的位设置为0即可。获取(或请求)ID需要搜索0位,如果找不到,则扩展BitArray。

    如果您仍然可以选择扩展您的 BitArray(即您还没有达到 512MB),您可能不想在决定扩展之前搜索所有 BitArray - 一直这样做会很慢。您当然不会总是希望从同一个索引开始:跟踪您找到的最后一个 0 并从那里开始搜索可能是个好主意。

    我可以看到的一个优势是一旦所有或几乎所有对象都被释放,内存使用情况。那么 Tom Panning 的解决方案需要的内存至少是这个的 32 倍。但是,我希望在典型用法中该解决方案使用较少。

    【讨论】:

    • +1 因为它在少数情况下更好,因此应该考虑。不过,就像你说的,一般来说情况更糟,这就是我接受汤姆的原因。感谢您的回复!
    【解决方案2】:

    如果您确定已发布的 ID 可以安全地立即重复使用(即,不会有对旧 ID 的过时引用,如果新对象被分配了最近发布的 ID,则会混淆),您可以先使用发布的ID。所以当一个 ID 被释放时,你把它放在队列的末尾。当请求新 ID 时,您使用队列中的第一个 ID。如果队列为空,则增加内部计数器并给出新数字。

    此实施的优势:

    • 所有操作都是 O(1)。您永远不会迭代集合或范围。您只能在队列末尾插入、从队列前面移除或增加计数器。
    • 内存占用应该相当低,因为您正在尝试尽快用完队列。
    • 实施很简单。

    缺点:

    • 您将很快重用 ID,因此您不会使用整个索引范围来防止新对象使用与最近发布的对象相同的 ID。
    • 您甚至无法通过查看对象的 ID 来猜测对象的年龄。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 2012-02-22
      • 1970-01-01
      相关资源
      最近更新 更多