简体   繁体   中英

Generating a unique Id for a string using Java

I am currently working on a task where I need to append a unique identifier to a string and then create a table in redshift with that name. Currently I was using id.hashcode() to generate the identifier (and my query had create table if not exist) to do the task. But I recently got 1 id for which the generated hashcode is a negative value and Redshift does not allow "-" in the query (Sample name generated : abc-1234).

How can I uniquely identify each incoming Id and if table for that id exists I should not create the table again.

First, any hashcode will be, by definition, less unique than the string itself unless you use any more data to generate it like a timestamp.

You have several possibilities depending on the type of unique identifier that you want to append to the string and how unique you need it to be.

1ˢᵗ) A very close to universal unique identifier can be generated using a timestamp, the machine IP address and a random number with a method like this one:

public String createUniqueKey() {

    int iRnd;
    long lSeed = System.currentTimeMillis();
    Random oRnd = new Random(lSeed);
    String sHex;
    StringBuffer sUUID = new StringBuffer(32);
    byte[] localIPAddr = new byte[4];

    try {

        // 8 characters Code IP address of this machine
        localIPAddr = InetAddress.getLocalHost().getAddress();

        sUUID.append(byteToStr[((int) localIPAddr[0]) & 255]);
        sUUID.append(byteToStr[((int) localIPAddr[1]) & 255]);
        sUUID.append(byteToStr[((int) localIPAddr[2]) & 255]);
        sUUID.append(byteToStr[((int) localIPAddr[3]) & 255]);
    }
    catch (UnknownHostException e) {
        // Use localhost by default
        sUUID.append("7F000000");
    }

    // Append a seed value based on current system date
    sUUID.append(Long.toHexString(lSeed));

    // 6 characters - an incremental sequence
    sUUID.append(Integer.toHexString(iSequence.incrementAndGet()));

    iSequence.compareAndSet(16777000, 1048576);

    do {
        iRnd = oRnd.nextInt();
        if (iRnd>0) iRnd = -iRnd;
        sHex = Integer.toHexString(iRnd);
    } while (0==iRnd);

    // Finally append a random number
    sUUID.append(sHex);

    return sUUID.substring(0, 32);
} // createUniqueKey()

2ⁿᵈ) You may want to create a series of keys that increases or decreases over time so that you can sort on it:

private static AtomicInteger iSequence = new AtomicInteger(1048576);

/**
 * Create a universal unique key which increases over time
 * @return String of 32 characters length
 */
public String createTimeDependentKey() {
    char pad[];
    int padLen;
    StringBuilder retval = new StringBuilder(32);
    final long seed = System.currentTimeMillis();
    Random rnd = new Random(seed);
    // 10 characters time dependent part
    String timePart = String.valueOf(Long.MAX_VALUE-seed);
    padLen = timePart.length()-10;
    pad = new char[padLen];
    java.util.Arrays.fill(pad, '0');
    retval.append(pad).append(timePart);
    // 6 characters sequential
    retval.append(Integer.toHexString(iSequence.incrementAndGet()));
    iSequence.compareAndSet(16777000, 1048576);
    // 8 characters IP dependent part       
    try {
        byte[] localIPAddr = InetAddress.getLocalHost().getAddress();
        retval.append(byteToStr[((int) localIPAddr[0]) & 255]);
        retval.append(byteToStr[((int) localIPAddr[1]) & 255]);
        retval.append(byteToStr[((int) localIPAddr[2]) & 255]);
        retval.append(byteToStr[((int) localIPAddr[3]) & 255]);
    }
    catch (UnknownHostException e) {
        retval.append("7f000000");
    }
    // 8 characters random part
    String randomPart = String.valueOf(rnd.nextInt(Integer.MAX_VALUE));
    padLen = timePart.length()-8;
    retval.append(randomPart).append(generateRandomId(padLen, "0123456789abcdef", Character.LOWERCASE_LETTER));
    return retval.toString();
}

/**
 * Generate a reverse timestamp plus random int identifier of 32 characters length
 * The identifier will be composed of Long.MAX_VALUE-Current Time in Milliseconds followed by a random 32 bits integer
 * @return Numeric identifier of 32 characters length padded with zeros at the left
 */
public String generateReverseTimestampId() {
  String sTs = Str.leftPad(String.valueOf(Long.MAX_VALUE-System.currentTimeMillis()),'0',20);
  String sRd = Str.leftPad(String.valueOf(new Random().nextInt(Integer.MAX_VALUE)),'0',10);
  return Str.leftPad(sTs+sRd,'0',32);
}

3ʳᵈ) You may want to create a pseudo-unique key with only a given set of characters:

public String generateRandomId(int iLength, String sCharset, byte byCategory ) throws StringIndexOutOfBoundsException {

  if (iLength<=0) 
    throw new StringIndexOutOfBoundsException("Uid.generateRandomId() identifier length must be greater than zero");

  if (iLength>4096) 
    throw new StringIndexOutOfBoundsException("Uid.generateRandomId() identifier length must be less than or equal to 4096");

  if (sCharset!=null) {
    if (sCharset.length()==0) throw new StringIndexOutOfBoundsException("Uid.generateRandomId() character set length must be greater than zero");
  } else {
    sCharset = "abcdefghjkmnpqrstuvwxyz23456789";
  }

if (byCategory!=Character.UNASSIGNED && byCategory!=Character.UPPERCASE_LETTER && byCategory!=Character.LOWERCASE_LETTER)
  throw new IllegalArgumentException("Uid.generateRandomId() Character category must be one of {UNASSIGNED, UPPERCASE_LETTER, LOWERCASE_LETTER}");

int iCsLen = sCharset.length();
  StringBuilder oId = new StringBuilder(iLength);
  Random oRnd = new Random();
  for (int i=0; i<iLength; i++){
    char c = sCharset.charAt(oRnd.nextInt(iCsLen));
    if (byCategory==Character.UPPERCASE_LETTER)
      c = Character.toUpperCase(c);
    else if (byCategory==Character.LOWERCASE_LETTER)
      c = Character.toLowerCase(c);
    oId.append(c);
  }
  return oId.toString();
} 

You´ll also need this array

private static String[] byteToStr = {
    "00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
    "10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
    "20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
    "30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
    "40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
    "50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
    "60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
    "70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
    "80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
    "90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
    "a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
    "b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
    "c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
    "d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
    "e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
    "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff" };

A full implementation can be found here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM