生成唯一 ID 并放入 Map<String, Entity>
中的好算法是什么?实体是可以包含其他实体的容器/文件夹类,而字符串是 ID?我认为在生成新实体时,它应该始终使用其父实体的 ID,所以现在我所做的是
(Math.abs((parentName+entityName).hashCode())).toString;
但它似乎效率很低,因为 ID 可以是字符串但可能不包含“-”,因此它只包含数字,而它也可能包含字母,而 Math.abs 将可能的 ID 数量减半。哦,ID 必须具有相同的长度(8 个字母)。它只需在 map 和 XML 文件中用作 key ,并且不必是安全的。
最佳答案
将父 ID 包含在子 ID 中似乎没有任何优势。这样做的一个潜在优势是通过父 ID 查找所有子代(即返回所有以 parent_id 开头的 ID),但是您正在散列连接的 ID 并且您有一个最大 ID 长度,这使得这种方法不可行。
如果您的 key 不必是安全的,那么计数器将是高效的并保证唯一性。一个示例实现是生成由区分大小写的字母数字组成的 ID,这将为您提供大约 10^14 个 ID(您还可以添加特殊字符以增加 ID 的数量)。您需要一个包含 62 个字符的数组:索引 0-25 为小写字母,索引 26-51 为大写字母,索引 52-61 为数字。您还需要一个由 8 个整数(或短整数或字节)组成的状态数组,初始化为全 0。要检索 id,请使用状态数组查找字符数组中的字符并将它们连接在一起(因此 {0, 1, 2, 0, 1, 2, 0, 1} 的状态生成“abcabcab”的 id );然后增加状态数组的第 0 个索引,如果这导致数字大于 61,则将第 0 个索引设置为 0 并增加状态数组的第 1 个索引,如果这导致数字大于 61,则设置第 1 个索引到 0 并增加状态数组的第二个索引等。
我建议您使用 StringBuilder连接子字符串,否则你会生成很多垃圾字符串。您也可以使用 StringBuilder 替换状态数组,使用 StringBuilder#replace 代替 int/short/byte 增量操作。
如果您的应用程序是多线程的,那么计数器可能会成为瓶颈。解决此问题的一种方法是为每个工作线程保留 62 或 62^2 个 ID,例如:ID_Thread
是具有 ID 生成器的线程,其 getBatchId
方法同步并返回状态数组的副本。 ID_Thread
递增状态数组的 2nd 索引(不是第 0 个索引),如果这导致数字大于 61,则它将第 2 个索引设置为 0 并递增第 3 个索引等。同时,Worker_Thread
调用了 getBatchId
,现在有一个状态数组的副本;它使用它来生成 id,之后它递增状态数组的第 0 个索引,如果这导致数字大于 61,则它将第 0 个索引设置为 0 并递增第 1 个索引,如果这导致数字更大比 61 则调用 getBatchId
获取新的状态数组。这意味着 Worker_Thread
实例只需要为每 62^2 个 id 中的一个调用同步方法。
另一种多线程实现方式是 Id_Thread
不断生成 ID 并将它们放入 BlockingQueue
(最大队列大小为 32),其中Worker_Thread
实例从该队列中提取 ID。
关于Java算法String-ID-生成分层父子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26888335/