【问题标题】:Generate Unique Identifier in Very Big Loop - Java在非常大的循环中生成唯一标识符 - Java
【发布时间】:2013-12-25 07:20:01
【问题描述】:

我要问的问题很老了,我认为它问了 5-10 次。

但我的情况不同。

在让这么多明智(过度)的 SO 用户重复之前阅读我的问题。

我正在我的应用程序中导入包含 10K 条记录的 CSV 工作表。

我的逻辑按以下方式工作,

(1) 验证和导入工作表 (2) 如果记录不存在则保存到数据库中

对工作表的每条记录都执行第 2 步。

在步骤 -2 中,我必须生成 UUID 以稍后识别特定记录,

在我的第一个解决方案中

// this might be unique in some cases
String id = UUID.randomUUID().toString();

但我检查了它是否在每种情况下都会生成唯一的 id,例如 如果我一张一张地导入 10 张纸,其中有不同的记录,那么我得到了 10 次 在每次导入和保存操作中,数据库中的重复键错误至少 4000 次,

这意味着在 10,000 个密钥生成中,它仅生成 6000 个唯一 ID。

然后我生成一个长度为 6 的字母数字代码,类似于

eSv3h7

并将其附加到先前生成的 id 中,从而获得以下 id

d545f2b2-63ab-4703-89b0-f2f8eca02154-eSv3h7

经过测试还是有id重复的问题。

我也尝试了这里和其他网站上提到的几种组合,但仍然存在相同的 id 重复问题,

现在我想知道这只发生在循环中保存的 10k 条记录中,实际上我需要导入其中包含 800 万条记录的工作表

那么在我的特殊情况下如何解决生成唯一 ID 的问题?

更新 1 - 基于所有 cmets

在你最后试试这个东西。

循环 1 到 10,000 在循环中生成 uuid 将其存储在简单文本文件中的某个位置

然后制作一个简单的程序来从中查找重复项,如果您在第一次尝试中没有找到任何重复项,请一次又一次地重复上述所有步骤,我相信您会找到重复项。

过去我也坚信 UUID 永远不会产生重复的同一件事,分享我你的上述测试结果。

更新 2 - 代码

这是被调用者方法循环保存的工作表的每条记录所调用的方法。

@Override

public void preSynchronizedServiceExecution(ServiceData sData,
            ValueObject valueObject) throws BlfException {

        PropertyVO pVO = (PropertyVO) valueObject;

        ArrayList<CountyAuctionPropertyVO> capList = pVO
                .getCountyAuctionPropertyList();

        for (CountyAuctionPropertyVO caVO : capList) {

            TadFrameworkUtil.processValueObjectKeyProperty(caVO, true);

            TadFrameworkUtil.processValueObjectKeyProperty(caVO
                    .getPropertyLastOwner(), true);

            TadFrameworkUtil.processValueObjectKeyProperty(caVO
                    .getPropertyLastOwner().getAdd(), true);

        }

        ArrayList<PropertyAminitiesVO> amList = pVO.getPropertyAminitiesList();

        for (PropertyAminitiesVO pamVO : amList) {

            TadFrameworkUtil.processValueObjectKeyProperty(pamVO, true);

        }

        ArrayList<PropertyAttributesVO> atList = pVO
                .getPropertyAttributesList();

        for (PropertyAttributesVO patVO : atList) {

            TadFrameworkUtil.processValueObjectKeyProperty(patVO, true);

        }

        TadFrameworkUtil.processValueObjectKeyProperty(pVO, true);

        TadFrameworkUtil.processValueObjectKeyProperty(pVO.getSiteAdd(), true);
    }

下面是id生成方法

public static String generateUUID() throws BlfException {

        // this might be unique in some cases
        String id = UUID.randomUUID().toString();

        // introduce custom random string in mixing of upper and lower
        // alphabets,
        // which is 6 character long
        // and append it to generated GUID.
        String rs = randomString(6);

        id = id.concat("-").concat(rs);

        return id;
    }

更新 3(添加方法)

public static void processValueObjectKeyProperty(ValueObject valueObject,
            boolean create) throws BlfException {

        String key = (String) BlfConverter.getKey(valueObject);

        if (!StringUtility.isStringNonEmpty(key)) {
            throw new BlfException(valueObject.getObjectName()
                    + "-  key property does not exist.");
        }

        if (create) {

            String id = generateUUID();

            valueObject.setProperty(key, id);
        } else {

            String exisitingId = valueObject.getProperty(key);

            if (!StringUtility.isStringNonEmpty(exisitingId)) {

                String id = generateUUID();

                valueObject.setProperty(key, id);
            }
        }
    }

随机字符串方法只是2行的简单方法,生成长度为6的字母数字随机字符串。

如果您需要更多信息,请询问我,以便我可以在这里发布。

更新 4(生成的 UUID 示例)

d545f2b2-63ab-4703-89b0-f2f8eca02154-eSv3h7
6f06fa28-6f36-4ed4-926b-9fef86d002b3-DZ2LaE
20142d05-f456-4d72-b845-b6819443b480-xzypQr
67b2a353-e7b4-4245-90a0-e9fca8644713-AgSQZm
8213b275-2cb1-4d37-aff0-316a47e5b780-vMIwv9

如果我需要从数据库中获取它,我会从数据库中获得准确的结果。

谢谢

【问题讨论】:

  • 你能分享你的整个方法吗? UUID 应该为这个用例生成足够唯一的 ID...
  • 您可能想要做的是获取将产生密钥的随机化的种子(整数)。然后,检查该值是否已填充到数据库中。只是一个想法。\
  • 那么对generateUUID 方法的实际调用在哪里?
  • 但是generateUUID 的电话在哪里?我已经逐行阅读了您的代码,但我看不到它。
  • Set&lt;UUID&gt; uuidset = new HashSet&lt;UUID&gt;(); for(int i=0; i&lt;1000000; i++) { UUID newUUID = UUID.randomUUID(); if(uuidset.contains(newUUID)) throw new Exception("UUID " + newUUID + " is a duplicate"); uuidset.add(newUUID); } 不会导致一百万次迭代和几次运行中的单个重复。

标签: java


【解决方案1】:

感谢所有认真研究我的问题并花时间帮助我解决问题的用户。

我发现错误在业务逻辑基础的数据库层。

其中一个对象需要更新,但它是使用以前创建的 现有的 id,所以我得到了重复的主键错误。

我为 id 生成开发了一个单元测试,并测试了 UUID 超过 十亿个key,保证唯一,全都是真的 情况。

再次感谢大家。

【讨论】:

    猜你喜欢
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多