Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何为给定字符串创建唯一的序列号?_Java_Unique_Factory - Fatal编程技术网

Java 如何为给定字符串创建唯一的序列号?

Java 如何为给定字符串创建唯一的序列号?,java,unique,factory,Java,Unique,Factory,因此,我试图创建一个类,它表示给定人员的虚拟许可证号。许可证编号由以下内容构成: 此人姓名的首字母缩写 颁发许可证的年份 随机的任意序列号 例如,玛姬·史密斯(Maggie Smith)的执照是在1990年颁发的,其执照号码可能是MS-1990-11,11是序列号。然而,马克·桑德斯可能在同一年获得了驾照,这意味着他的驾照也可能是MS-1990 这就是问题所在。我需要确认这个人的序列号和玛姬的不一样。因此,我必须检查所有具有相同首字母和发行年份的记录,然后生成一个新的唯一序列号。以下是我目前

因此,我试图创建一个类,它表示给定人员的虚拟许可证号。许可证编号由以下内容构成:

  • 此人姓名的首字母缩写
  • 颁发许可证的年份
  • 随机的任意序列号
例如,玛姬·史密斯(Maggie Smith)的执照是在1990年颁发的,其执照号码可能是MS-1990-11,11是序列号。然而,马克·桑德斯可能在同一年获得了驾照,这意味着他的驾照也可能是MS-1990

这就是问题所在。我需要确认这个人的序列号和玛姬的不一样。因此,我必须检查所有具有相同首字母和发行年份的记录,然后生成一个新的唯一序列号。以下是我目前的代码:

public class LicenceNumber {

private final Name driverName;
private final Date issueDate;
private static final Map<String, LicenceNumber> LICENCENOS = new HashMap<String, LicenceNumber>();

public LicenceNumber(Name driverName, Date issueDate){

    this.driverName = driverName;
    this.issueDate = issueDate;
}

public static LicenceNumber getInstance(Name driverName, Date issueDate){
    Calendar tempCal = Calendar.getInstance();
    tempCal.setTime(issueDate);
    String issueYear = String.valueOf(tempCal.get(Calendar.YEAR));
    int serialNo = 1;
    String k = driverName.getForename().substring(0, 1) + driverName.getSurname().substring(0, 1) + "-" + issueYear + "-" + serialNo;

    if(!LICENCENOS.containsKey(k)){
        LICENCENOS.put(k, new LicenceNumber(driverName,issueDate));
    }

    return LICENCENOS.get(k);
}

public boolean isUnique(){
    return true;
}

public Name getDriverName() {
    return driverName;
}

public Date getIssueDate() {
    return issueDate;
}
}

我基于一些课堂讲稿,讨论了如何利用工厂实现独特性。我也不确定是应该使用getInstance还是通过创建新对象来创建LicenceNumber。有人知道我可以用什么方法检查给定字符串的序列号,例如XX-XXXX是否已经存在吗?

这里有一种方法可以在程序期间创建增量数字。由于没有备份数据库,程序的每次运行都将重置

它通过使用原子整数来确保唯一性。我使用了
ConcurrentMap
来利用线程安全以及
.putIfAbsent
方法。但是,它可以很容易地转换为使用标准的
地图
。我还使用了
字符串
,但更好的方法是使用真正的域对象。这足以处理OP的问题并用于说明目的

// a Map for holding the sequencing
private ConcurrentMap<String, AtomicInteger> _sequence = 
        new ConcurrentHashMap<>();

/**
 * Returns a unique, incrementing sequence, formatted to
 * 0 prefixed, 3 places, based upon the User's initials
 * and the registration year
 */
public String getSequence(String initials, String year)
{
    String key = makePrefix(initials, year);
    AtomicInteger chk = new AtomicInteger(0);
    AtomicInteger ai = _sequence.putIfAbsent(key, chk);
    if (ai == null) {
        ai = chk;
    }

    int val = ai.incrementAndGet();

    String fmt = String.format("%03d", val);

    return fmt;
}

/**
 * A helper method to make the prefix, which is the
 * concatintion of the initials, a "-", and a year.
 */
private String makePrefix (String initials, String year)
{
    return initials + "-" + year;
}
示例输出:

高,1999:001
ac,1999:001
高,1999:002
ac,1999:002
ms,1999:001
ko,2001:001

为了融入OP的代码,建议进行以下修改:

public static LicenceNumber getInstance(Name driverName, Date issueDate){
  Calendar tempCal = Calendar.getInstance();
  tempCal.setTime(issueDate);
  String issueYear = String.valueOf(tempCal.get(Calendar.YEAR));

  // ** get the initials; I would actually move this functionality to be
  //   a method on the Name class
  String initials = driverName.getForename().substring(0, 1) + driverName.getSurname().substring(0, 1);

  // get the unique serial number
  String serial = getSequence(initials, issueYear);

  // make the full licenseplate String
  String k = makePrefix(initials, issueYear) + "-" + serial;

if(!LICENCENOS.containsKey(k)){
    LICENCENOS.put(k, new LicenceNumber(driverName,issueDate));
}

return LICENCENOS.get(k);

}

这有数据库支持吗?我的意思是,什么构成“存在”——在什么时间范围内?不,没有涉及数据库。如果我正确地实现了它,那么许可证号码存储在地图中,因此我必须在那里进行检查。我建议使用AtomicInteger。我将在稍后提供一个快速的答案。您需要小心线程问题。此外,如果您不担心MS-1980序列号中的“间隙”,您可以有一个主序列生成器。否则,每一组首字母和年份都需要一个序列生成器。为什么它们必须是随机的?为什么不只是序列号呢?似乎在使用getSequence()设置serialNumber时,我收到一个错误,说getSequence应该是静态的。另外,如何使用标准映射实现这一点?抱歉,遗漏了
getInstance()
是静态的(相关问题:为什么是静态的?)。因此,其他方法也需要是静态的。要使用标准的
映射
,请从它们中删除并发映射,然后从
putIfAbsent
更改为类似于
ai=\u sequence.get(key)的内容;如果(ai==null){ai=chk;_sequence.put(key,ai);}
。基本上,如果您阅读
putIfAbsent
的Javadoc,它会给出它所使用的算法。请注意,进行这些更改会删除线程安全性。我的缺点是,标准的
Map
有一个
putIfAbsent()
,因此理论上,您可以从
ConcurrentMap
/
CurrentHashMap
更改为
Map
/
HashMap
静态最终私有映射序列=new HashMap()啊,是的,这很好用。我之所以将getInstance设置为静态,是因为我基于一些课堂讲稿中给出的一个示例。有什么不应该的原因吗?很高兴答案有用!IMHO,
getInstance()
意味着一个单例模式;我希望
getInstance()
返回一些单例,而不是对象的特定实例化。如果我遵循这个想法,基本上你有一个构建器的方法,而不是使用构造函数。这种方法是可行的,但我会在代码审查中推动重构,因为太多的方法和变量必须是静态的,而
LicenseNumber
的构造函数是公共的。这意味着我可以
新建LicenseNumber()
,但它不会在“LicenseNos”映射中正确注册。
public static void main(String[] args)
{
    LicensePlate_37169055 lp = new LicensePlate_37169055();
    System.out.println("ko, 1999: " + lp.getSequence("ko", "1999"));
    System.out.println("ac, 1999: " + lp.getSequence("ac", "1999"));
    System.out.println("ko, 1999: " + lp.getSequence("ko", "1999"));
    System.out.println("ac, 1999: " + lp.getSequence("ac", "1999"));
    System.out.println("ms, 1999: " + lp.getSequence("ms", "1999"));
    System.out.println("ko, 2001: " + lp.getSequence("ko", "2001"));

}
public static LicenceNumber getInstance(Name driverName, Date issueDate){
  Calendar tempCal = Calendar.getInstance();
  tempCal.setTime(issueDate);
  String issueYear = String.valueOf(tempCal.get(Calendar.YEAR));

  // ** get the initials; I would actually move this functionality to be
  //   a method on the Name class
  String initials = driverName.getForename().substring(0, 1) + driverName.getSurname().substring(0, 1);

  // get the unique serial number
  String serial = getSequence(initials, issueYear);

  // make the full licenseplate String
  String k = makePrefix(initials, issueYear) + "-" + serial;

if(!LICENCENOS.containsKey(k)){
    LICENCENOS.put(k, new LicenceNumber(driverName,issueDate));
}

return LICENCENOS.get(k);