How can I generate a random 7-character alphanumeric string? - java

I did the stuff like this but not working. the base48Encode method parameter I have passed the current system time in milli secs
private static final String CHARACTER_SET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ";
public static String base48Encode(double d) {
Double num = Double.valueOf(d);
Integer length = CHARACTER_SET.length();
String encodeString = new String();
while (num > length) {
encodeString = CHARACTER_SET.charAt(num.intValue() % length) + encodeString;
num = Math.ceil(new Double(num / length) - 1);
}
encodeString = CHARACTER_SET.charAt(num.intValue()) + encodeString;
return encodeString;
}

I won't get duplicate values in any scenario.
It's not possible to 100% guarantee a unique value (especially given a string of 7 characters) due to the Birthday Paradox. Given a character set containing 48 characters, selecting 7 at random, you'd have a 1% chance of collision after only 110,000 random values.
You can help mitigate this by doing two things.
Use a larger character set.
Increase the length of your random value.
Using a character set of 64 characters and selecting 10 at random would greatly decrease your chance of a collision, down to a 1% after 160,000,000 random values.
Rather than using currentTimeMillis to generate a value, which would cause a collision if you generated two values within the same millisecond, I'd suggest just using the Random class (which is seeded from the current time down to the nanosecond).
private static final String CHARACTER_SET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ";
private static Random rnd = new Random();
public static String randomString(int length){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < length; i++){
builder.append(CHARACTER_SET.charAt(rnd.nextInt(CHARACTER_SET.length())));
}
return builder.toString();
}

Related

Alpha Numeric Random Number Sequence [5-digit or 6-digit or any digit] generation

Hi I am trying to generate a 5 digit random number which is alpha numeric in nature. I am doing both with without using Streams.
CODE
public class AlphaRandom {
private static final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static final Random random = new Random();
public static void main(String args[]) {
int length = 5;
String seq = randomAlphaNumeric(length);
System.out.println("Random Number Normal : " +seq);
IntStream.range(0,1).forEach(i->System.out.println("Random Number Streams : " +generateRandomString(random, length)));
}
// Using Streams
private static String generateRandomString(Random random, int length){
return random.ints(48,122)
.filter(i-> (i<57 || i>65) && (i <90 || i>97))
.mapToObj(i -> (char) i)
.limit(length)
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
}
// Normal
public static String randomAlphaNumeric(int count) {
StringBuilder builder = new StringBuilder();
while (count-- != 0) {
int character = (int)(Math.random()*ALPHA_NUMERIC_STRING.length());
builder.append(ALPHA_NUMERIC_STRING.charAt(character));
}
return builder.toString();
}
}
Sample Outputs :
Random Number Normal : VYAXC
Random Number Streams : LdBN6
Random Number Normal : 2ANTT
Random Number Streams : hfegc
Random Number Normal : JWK4Y
Random Number Streams : 8mQXK
But I am unable to generate the sequence always starting with a UpperCase only.
Can someone help me out.
I will use RandomStringUtils from the apache library to do this. The reason to do this is less code and I believe better readability of the code.
This is my code which can do the required thing
import org.apache.commons.lang3.RandomStringUtils;
public class GenerateRandomString {
public static void main(String[] args) {
int keyLength = 5; // Number of character allowed as per requirement
String randomAlphanumeric = RandomStringUtils.randomAlphanumeric(keyLength);
System.out.println("randomAlphanumeric generated is " + randomAlphanumeric);
String upperCaseRandom = randomAlphanumeric.substring(0, 1).toUpperCase() + randomAlphanumeric.substring(1);
System.out.println("upperCaseRandom generated is " + upperCaseRandom);
}
}
It would generate the following output:
randomAlphanumeric generated is m8OiR
upperCaseRandom generated is M8OiR
I am making the first character to uppercase as required by question using the substring method.
The easiest way is that before to return your string (once you have generated it), you take the first letter in order to apply toUpperCase and on the remaining chars, apply toLowerCase. Also, if in the future you will need to generate longer strings, you can use the same method without changing anything.
Summering what we'll do is:
public static String manipulate (String rand){
String c = rand.substring(0,1); // where rand is the random alphanumeric generated by your methods, we pick the first char
c = c.toUpperCase(); //we make it upperCase
String split = rand.substring(1); //we get the remaining of the string starting from position 1
split = split.toLowerCase(); //let's apply lowercase on the remaining
String result = c+split; //join again
return result;
}
Full Code:
package test;
import java.util.Random;
import java.util.stream.IntStream;
public class AlphaRandom {
private static final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static final Random random = new Random();
public static void main(String args[]) {
int length = 5;
String seq = randomAlphaNumeric(length);
System.out.println("Random Number Normal : " +seq);
IntStream.range(0,1).forEach(i->System.out.println("Random Number Streams : " +generateRandomString(random, length)));
}
public static String manipulate (String rand){
String c = rand.substring(0,1); // where rand is the random alphanumeric generated by your methods, we pick the first char
c = c.toUpperCase(); //we make it upperCase
String split = rand.substring(1); //we get the remaining of the string starting from position 1
split = split.toLowerCase(); //let's apply lowercase on the remaining
String result = c+split; //join the again
return result;
}
// Using Streams
private static String generateRandomString(Random random, int length){
String rand = random.ints(48,122)
.filter(i-> (i<57 || i>65) && (i <90 || i>97))
.mapToObj(i -> (char) i)
.limit(length)
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
return manipulate(rand);
}
// Normal
public static String randomAlphaNumeric(int count) {
StringBuilder builder = new StringBuilder();
while (count-- != 0) {
int character = (int)(Math.random()*ALPHA_NUMERIC_STRING.length());
builder.append(ALPHA_NUMERIC_STRING.charAt(character));
}
return manipulate(builder.toString());
}
}
Output:
Random Number Normal : Mwwsz
Random Number Streams : Q1fqk

Java Random Color String

I have written this java method but sometimes the color String is only 5 characters long. Does anyone know why?
#Test
public void getRandomColorTest() {
for (int i = 0; i < 20; i++) {
final String s = getRandomColor();
System.out.println("-> " + s);
}
}
public String getRandomColor() {
final Random random = new Random();
final String[] letters = "0123456789ABCDEF".split("");
String color = "#";
for (int i = 0; i < 6; i++) {
color += letters[Math.round(random.nextFloat() * 15)];
}
return color;
}
Working with floats and using round is not a safe way of creating such random colors.
Actually a color code is an integer in hexadecimal formatting. You can easily create such numbers like this:
import java.util.Random;
public class R {
public static void main(String[] args) {
// create random object - reuse this as often as possible
Random random = new Random();
// create a big random number - maximum is ffffff (hex) = 16777215 (dez)
int nextInt = random.nextInt(0xffffff + 1);
// format it as hexadecimal string (with hashtag and leading zeros)
String colorCode = String.format("#%06x", nextInt);
// print it
System.out.println(colorCode);
}
}
DEMO
Your split will generate an array of length 17 with an empty string at the beginning. Your generator occasionally draws that zeroth element which will not contribute to the length of the final string. (As a side effect, F will never be drawn.)
Accept that split has that odd behaviour and work with it: Ditch that nasty formula that uses round. Use 1 + random.nextInt(16) instead as your index.
Don't recreate the generator on each call of getRandomColor: that ruins the generator's statistical properties. Pass random as a parameter to getRandomColor.
Also to ensure that your String always contains 6 characters, try to replace the for loop with a while. Please see:
while (color.length() <= 6){
color += letters[random.nextInt(17)];
}

Java takes long to convert a 5 letter word to numbers

Before I start I would like to inform you that I am a total beginner to Java so excuse my uneducated mistakes. I have been trying to program an application to encrypt a message. During this process, the input gets converted to a number to allow mathematical expressions. The problem is when trying to convert. The actual code does work, but takes a rather long time to convert a 5 letter word, which is the word "Hello"( it takes around 10 seconds or so). Below is the method where the input gets converted. `
public static void encrypt(String plainText) {
Random random = new Random();
plainText =plainText.toUpperCase();
char[] storedInput = plainText.toCharArray();
int[] convertedInput = new int[plainText.length()];
for (int indexSelector = 0, comparisonNumber = 1; indexSelector < plainText.length(); comparisonNumber++) {
if( storedInput[indexSelector] == ' ') {
System.out.print(" <SPACE> ");
}
else {
if( ((int) storedInput[indexSelector]-64) == comparisonNumber) {
int converter = storedInput[indexSelector] - 64;
convertedInput[indexSelector] = converter;
System.out.print(convertedInput[indexSelector]);
}
else {
continue;
}
}
}
}
This code takes an input (hello), turns all letters to upper case, and then when I get the integer I subtract 64 because it returns the ASCII integer. After this A becomes 1, B becomes 2, C becomes 3 and so on....
When I try to convert hello (or any other words) it takes at least 8 seconds. Any suggestions on why?
You need to simplify your program. comparisonNumber is causing you significant problems, and you generally should avoid multiple variables in your for loop unless you really know what you are doing. Even in professional settings I would consider a , in a for loop a problem that needs to be justified.
In your case you are looping on comparisonNumber but never using it for anything but verifying you hit the right number, where you then ignore the value and do operations that are independent of it. Since you don't reset the value, it loops through all the possible values before continuing to process the next letter.
Here is a version that might be closer to what you are looking for, I just removed that variable and left everything else as is.
public static void encrypt(String plainText) {
Random random = new Random();
plainText.toUpperCase();
char[] storedInput = plainText.toCharArray();
int[] convertedInput = new int[plainText.length()];
for (int indexSelector = 0; indexSelector < plainText.length(); indexSelector++) {
if( storedInput[indexSelector] == ' ') {
System.out.print(" <SPACE> ");
} else {
int converter = storedInput[indexSelector] - 64;
convertedInput[indexSelector] = converter;
System.out.print(convertedInput[indexSelector]);
indexSelector++;
}
}

Generating Alphanumeric random string in Java [duplicate]

This question already has answers here:
How to generate a random alpha-numeric string
(46 answers)
Closed 9 years ago.
I am using String Builder from another answer, but I can't use anything but alpha/numeric, no whitespace, punctuation, etc. Can you explain how to limit the character set in this code? Also, how do I insure it is ALWAYS 30 characters long?
Random generator = new Random();
StringBuilder stringBuilder = new StringBuilder();
int Length = 30;
char tempChar ;
for (int i = 0; i < Length; i++){
tempChar = (char) (generator.nextInt(96) + 32);
stringBuilder.append(tempChar);
I have looked at most of the other answers, and can't figure out a solution to this.
Thanks. Don't yell at me if this is a duplicate. Most of the answers don't explain which part of the code controls how long the generated number is or where to adjust the character set.
I also tried stringBuilder.Replace(' ', '1'), which might have worked, but eclipse says there is no method for Replace for StringBuilder.
If you want to control the characterset and length take for example
public static String randomString(char[] characterSet, int length) {
Random random = new SecureRandom();
char[] result = new char[length];
for (int i = 0; i < result.length; i++) {
// picks a random index out of character set > random character
int randomCharIndex = random.nextInt(characterSet.length);
result[i] = characterSet[randomCharIndex];
}
return new String(result);
}
and combine with
char[] CHARSET_AZ_09 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
to specify the characterset.
It's not based on StringBuilder since you know the length and don't need all the overhead.
It allocates a char[] array of the correct size, then fills each cell in that array with a randomly chosen character from the input array.
more example use here: http://ideone.com/xvIZcd
Here's what I use:
public static String randomStringOfLength(int length) {
StringBuffer buffer = new StringBuffer();
while (buffer.length() < length) {
buffer.append(uuidString());
}
//this part controls the length of the returned string
return buffer.substring(0, length);
}
private static String uuidString() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
You may try this:
//piece
int i = 0;
while(i < length){
char temp =(char) (generator.nextInt(92)+32);
if(Character.isLetterOrDigit(temp))
{
stringBuilder.append(temp);
++i;
}
}
System.out.println(stringBuilder);
Should achieve your goal

A short as possible unique ID

I'm making a tool for optimizing script and now I want to compress all names in it to the minimum.
I got the function started for it, but it somehow bugs and stops after length 2 is exceeded.
Is there an easier way to do this? I just need a pattern that generates a String starting from a -> z then aa -> az ba -> bz and so on.
public String getToken() {
String result = ""; int i = 0;
while(i < length){
result = result + charmap.substring(positions[i], positions[i]+1);
positions[length]++;
if (positions[current] >= charmap.length()){
positions[current] = 0;
if ( current < 1 ) {
current++;length++;
}else{
int i2 = current-1;
while( i2 > -1 ){
positions[i2]++;
if(positions[i2] < charmap.length()){
break;
}else if( i2 > 0 ){
positions[i2] = 0;
}else{
positions[i2] = 0;
length++;current++;
}
i2--;
}
}
}
i++;
}
return result;
}
UNLIKE THE OTHER QUESTIONS!! I dont just want to increase an integer, the length increases to much.
Here's one I used
public class AsciiID {
private static final String alphabet=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int currentId;
public String nextId() {
int id = currentId++;
StringBuilder b = new StringBuilder();
do {
b.append(alphabet.charAt(id % alphabet.length()));
} while((id /=alphabet.length()) != 0);
return b.toString();
}
}
I would use a base 36 or base 64 (depending on case sensitivity) library and run it with an integer and before you output, convert the integer to a base 36/64 number. You can think in terms of sequence, which is easier, and the output value is handled by a trusted library.
You can use:
Integer.toString(i++, Character.MAX_RADIX)
It's base36. It will be not as greatly compressed as Base64 but you have a 1-line implementation.
You could search for some library that operates numbers of any radix, say 27, 37 or more. Then you output that number as alphanumeric string (like HEX, but with a-zA-Z0-9).
Well let's assume we can only output ASCII (for unicode this problem gets.. complicated): As a quick look shows its printable characters are in the range [32,126]. So to get the most efficient representation of this problem we have to encode a given integer in base 94 so to speak and add 32 to any generated char.
How you do that? Look up how Sun does it in Integer.toString() and adapt it accordingly. Well it's probably more complex than necessary - just think about how you convert a number into radix 2 and adapt that. In its simplest form that's basically a loop with one division and modulo.
In your tool you need to create a dictionary, which will contain an unique integer id for each unique string and the string itself. When adding strings to the dictionary you increment given id for each newly added unique string. Once dictionary is completed, you can simply convert ids to String using something like this:
static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static final int CHARS_LENGTH = CHARS.length();
public String convert(int id) {
StringBuilder sb = new StringBuilder();
do {
sb.append(CHARS.charAt(id % CHARS_LENGTH));
id = id / CHARS_LENGTH;
} while(id != 0);
return sb.toString();
}
This function generates the Nth Bijective Number (except zeroth). This is the most optimal coding ever possible. (The zeroth would be an empty string.)
If there were 10 possible characters, 0-9, it generates, in order:
10 strings of length 1, from "0" to "9"
10*10 strings of length 2, from "00" to "99"
10*10*10 strings of length 3, from "000" to "999"
etc.
The example uses 93 characters, because I just happened to need those for Json.
private static final char[] ALLOWED_CHARS =
" !#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"
.toCharArray();
private static final AtomicInteger uniqueIdCounter = new AtomicInteger();
public static String getToken() {
int id = uniqueIdCounter.getAndIncrement();
return toBijectiveNumber(id, ALLOWED_CHARS);
}
public static String toBijectiveNumber(int id, char[] allowedChars) {
assert id >= 0;
StringBuilder sb = new StringBuilder(8);
int divisor = 1;
int length = 1;
while (id >= divisor * allowedChars.length) {
divisor *= allowedChars.length;
length++;
id -= divisor;
}
for (int i = 0; i < length; i++) {
sb.append(allowedChars[(id / divisor) % allowedChars.length]);
divisor /= allowedChars.length;
}
return sb.toString();
}

Categories