【问题标题】:Java, Generating a unique serial number using Maps/CollectionsJava,使用 Maps/Collections 生成唯一的序列号
【发布时间】:2021-02-21 03:39:32
【问题描述】:

我目前有一个类负责生成唯一序列号,提供参数“全名”和“年份”。

public static CustomerNumber getInstance(CustomerName name, Date dateIssued) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(dateIssued);
    int yearIssued = cal.get(Calendar.YEAR);

    return name.getFirstName().charAt(0) + name.getLastName().charAt(0) + "-" + yearIssued + "-" + serialNumber;
}

预期的结果是这样的:

“约翰·史密斯”,2018 年 --> JS-2018-01,

“乔·斯科特”,2018 --> JS-2018-02,

'贾登·斯科特',2018 --> JS-2018-03

“玛吉·斯科特”,2018 年 --> MS-2018-01,

基本上,如果前缀(姓名首字母和年份)已经存在,则必须应用序列号增量来表示它是一个新人。

我尝试应用某种 Map,但我是 java/ 编程新手,想要一些建议

【问题讨论】:

  • 为什么要使用地图? (不是说错了,只是想按照你的思路来)
  • @AleZalazar 老实说,这是一种打击和希望。可能将前缀作为键,将值作为最后的数字。如果前缀存在,则返回该值并将其加一并将其设置为新值?如果这是可能的:/
  • 绝对可以,您可以使用Map<String, Integer> map = new HashMap<>(); 并放置/获取您的东西。

标签: java collections hashmap


【解决方案1】:

一种方法是使用HashMap<String, Integer>。该映射将存储用作serialNumber 的最后一个值。每次计算新客户的 ID 时,使用 merge 增加哈希映射的值。

private static Map<String, Integer> serialNumbersMap = new HashMap<>();

public static CustomerNumber getInstance(CustomerName name, LocalDate dateIssued) {
    // I recommend you use java.time.LocalDate here
    int yearIssued = dateIssued.getYear();

    String key = name.getFirstName().charAt(0) + name.getLastName().charAt(0) + "-" + yearIssued;

    int serialNumber = serialNumbersMap.merge(key, 1, Integer::sum);
    String id = key + (serialNumber < 10? "-0": "-") + serialNumber;
    return id;
}

如果可以使用相同的客户名称和日期多次调用 getInstance,并且您希望在这种情况下返回相同的 ID,则需要另一个映射来存储已知的客户 ID。

private static Map<String, String> knownIDsMap = new HashMap<>();

如果您以前看过客户名称,请先查看此地图。如果没有,请执行上述操作,否则返回地图中的值。

public static CustomerNumber getInstance(CustomerName name, LocalDate dateIssued) {
    int yearIssued = dateIssued.getYear();

    String knownIDKey = name.getFirstName() + name.getLastName() + yearIssued;

    String knownID = knownIDsMap.get(knownIDKey);

    if (knownID != null) {
        return knownID;
    }

    // same as above...

    knownIdsMap.put(knownIDKey, id);
    return id;
}

为了更好的实现,创建一个类CustomerIDInfo,封装CustomerNameLocalDate,覆盖equalshashcode。然后您可以制作HashMap&lt;CustomerIDInfo, String&gt; 类型的地图,而无需进行所有这些字符串操作。

【讨论】:

  • 您好,非常感谢您的帮助!然而,我只是无法解决这条线。 serialNumbersMap.compute(key, (k, v) => v == null ? 1 : v + 1);
  • @rabin-bhandari 那行基本上说。获取serialNumbersMap.get(key) 的值。如果为空,则为serialNumbersMap.put(key, 1),否则为serialNumbersMap.put(key, serialNumbersMap.get(key) + 1)。而compute 返回与key 关联的新值。如您所见,所有这些逻辑都可以用compute 简洁地编写。
【解决方案2】:

所以,您只是想缓存生成的序列号并在重复时增加它,对吗?如果是这样,您只需要“设置”,您可以执行 while 循环来增加它,直到它是唯一的。

String baseValue = name.getFirstName().charAt(0) + name.getLastName().charAt(0) + "-" + yearIssued + "-";
String value = baseValue + serialNumber;
while(set.contains(value)){
    value = baseValue + (serialNumber++);
}
set.add(value);
return value;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-10
    • 2016-06-16
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多