Java 算法字符串 ID 生成分层父子项


生成

唯一 ID 以放入Map<String, Entity>的好算法是什么,其中实体是可以包含其他实体的容器/文件夹类,字符串是 ID?我认为在生成新实体时,它应该始终使用其父实体的 ID,所以现在我所做的是

(Math.abs((parentName+entityName).hashCode())).toString;

但它似乎效率很低,因为 ID 可以是字符串但可能不包含"-",所以它只包含数字,而它可能包含字母,而 Math.abs 将可能的 ID 数量减半。哦,ID必须具有相同的长度(8个字母)。它只需要在映射和XML文件中充当密钥,而不必是安全的。

子 ID 中包含父 ID 似乎没有任何好处。 这样做的一个潜在优势是通过父 id 查找所有子项(即返回所有以 parent_id 开头的 id),但您正在对串联的 id 进行哈希处理,并且您有一个最大 id 长度,这使得这种方法不可行。

如果您的密钥不必是安全的,那么计数器将是有效的并保证唯一性。 一个示例实现是生成由区分大小写的字母数字组成的 id,这将为您提供大约 10^14 个 id(您还可以添加特殊字符以增加 id 的数量)。 您需要一个包含 62 个字符的数组:索引 0-25 包含小写字母,索引 26-51 包含大写字母,索引 52-61 包含数字。 您还需要一个包含 8 个整数(或短整型或字节)的状态数组,初始化为所有 0。 要检索 id,请使用状态数组查找字符数组中的字符并将它们连接在一起(因此状态 {0, 1, 2, 0, 1, 2, 0, 1} 生成 id "abcabcab");然后递增状态数组的第 0 个索引,如果这导致一个大于 61 的数字,则将第 0 个索引设置为 0 并递增状态数组的第一个索引,如果这导致一个大于 61 的数字,则将第一个索引设置为 0 并递增状态数组的第 2 个索引, 等。

我建议你使用StringBuilder来连接子字符串,否则你会生成大量的垃圾字符串。 您还可以使用 StringBuilder 替换状态数组,使用 StringBuilder#replace 代替 int/short/byte 增量操作。


如果您的应用程序是多线程的,则计数器可能会成为瓶颈。 解决此问题的一种方法是让每个工作线程保留 62 或 62^2 个 id,例如:ID_Thread 是带有 id 生成器的线程,其 getBatchId 方法同步并返回状态数组的副本。 ID_Thread递增状态数组的第 2 个索引(不是第 0 个索引),如果这导致数字大于 61,则它将第二个索引设置为 0 并递增第 3 个索引,依此类推。 同时,Worker_Thread调用了getBatchId,现在有一个状态数组的副本;它使用它来生成 ID,然后递增状态数组的第 0 个索引,如果这导致一个大于 61 的数字,则它将第 0 个索引设置为 0 并递增第一个索引,如果这导致一个大于 61 的数字,那么它为一个新的状态数组调用 getBatchId。 这意味着Worker_Thread实例只需为每 62^2 个 id 中的一个调用同步方法。

另一种多线程实现是让Id_Thread不断生成 id 并将它们放置在BlockingQueue中(最大队列大小为 32),Worker_Thread 个实例从该队列中提取 ID。

最新更新