2016-05-11 3 views
1

Итак, я пытаюсь создать класс, представляющий вымышленный номер лицензии для данного человека. Номер лицензии строится из следующих функций:Как вы можете создать уникальный серийный номер для данной строки?

  • инициалов имени и фамилий
  • года лицензия была выдана лицом
  • Случайный произвольный серийный номер

Так, например, Мэгги Смит, чья лицензия была выпущена в 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; 
} 
} 

И фрагмент, как он может быть реализован:

public final class DrivingLicence { 

private final Name driverName; 
private final Date driverDOB; 
private final Date issueDate; 
private final LicenceNumber licenceNo; 
private final boolean isFull; 

public DrivingLicence(Name driverName, Date driverDOB, Date issueDate, boolean isFull){ 
    //TO-DO validate inputs 
    this.driverName = driverName; 
    this.driverDOB = driverDOB; 
    this.issueDate = issueDate; 
    this.licenceNo = LicenceNumber.getInstance(driverName, issueDate); 
    //this.licenceNo = new LicenceNumber(driverName, issueDate);//instantiate a licence number using the driverName and dateOfIssue 
    this.isFull = isFull; 
} 
} 

Я основывался на некоторых конспектах, которые обсуждают, как вы можете использовать заводы по уникальности. Я также не уверен, должен ли я создать LicenceNumber с помощью getInstance или путем создания нового объекта. Кто-нибудь знает, как я могу проверить, если серийный номер для данной строки, например. XX-XXXX уже существует?

+1

ли это поддерживается базой данных на всех?Я имею в виду, что представляет собой «существование» - за какие временные рамки? – KevinO

+0

Нет никакой базы данных. Если я внедрил его правильно, LicenceNumbers хранятся на Карте, поэтому я должен проверить там. –

+3

Я бы предложил AtomicInteger. На мгновение я дам быстрый ответ. – KevinO

ответ

3

Вот подход, который будет создавать инкрементные числа для длительности программы. Поскольку база данных резервного копирования отсутствует, каждый запуск программы будет сброшен.

Он работает с использованием AtomicInteger для обеспечения уникальности. Я использовал ConcurrentMap, чтобы воспользоваться безопасностью потоков, а также методом .putIfAbsent. Однако его можно легко преобразовать в стандартный Map. Я также просто использовал String, но лучшим подходом было бы использование реального объекта домена. Этого достаточно для решения вопроса ОП и для иллюстративных целей.

// 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; 
} 

Тестового пример:

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")); 

} 

Результат:

ко, 1999: 001
переменному ток, 1999: 001
ко, 1999: 002
переменного ток, 1999 : 002
мс, 1999: 001
ко, 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); 

}

+0

Похоже, что при установке serialNumber с помощью getSequence() у меня возникает ошибка, указывающая, что getSequence должен быть статическим. Кроме того, как это можно реализовать с помощью стандартной карты? –

+0

Простите, что 'getInstance()' является статическим (связанный вопрос: почему?). Таким образом, другие методы также должны быть статическими. Чтобы использовать стандартную «Map <>», удалите из них Concurrent, а затем измените с 'putIfAbsent' на нечто похожее на' ai = _sequence.get (key); if (ai == null) {ai = chk; _sequence.put (ключ, ai);} '. В принципе, если вы читаете Javadoc для 'putIfAbsent', он дает алгоритм, который он использует. Обратите внимание, что внесение этих изменений устраняет безопасность потоков. – KevinO

+0

Плохо, стандартная 'Карта' имеет' putIfAbsent() ', поэтому теоретически вы можете просто перейти от' ConcurrentMap'/'CurrentHashMap' к' Map'/'HashMap':' static final private Map _sequence = new HashMap <>(); ' – KevinO

Смежные вопросы