Is there functionality to generate a random character in Java?
Does Java have any functionality to generate random characters or strings? Or must one simply pick a random integer and convert that integer's ascii code to a character?
There are many ways to do this, but yes, it involves generating a random int (using e.g. java.util.Random.nextInt) and then using that to map to a char. If you have a specific alphabet, then something like this is nifty:
import java.util.Random;
//...
Random r = new Random();
String alphabet = "123xyz";
for (int i = 0; i < 50; i++) {
System.out.println(alphabet.charAt(r.nextInt(alphabet.length())));
} // prints 50 random characters from alphabet
then taking the first n chars, you get a random string of length n. The final code is simply:
public String randomString(int n) {
return $('a', 'z').shuffle().slice(n).toString();
}
NB: the condition n > 0 is cheched by slice
EDIT
as Steve correctly pointed out, randomString uses at most once each letter. As workaround
you can repeat the alphabet m times before call shuffle:
public String randomStringWithRepetitions(int n) {
return $('a', 'z').repeat(10).shuffle().slice(n).toString();
}
or just provide your alphabet as String:
public String randomStringFromAlphabet(String alphabet, int n) {
return $(alphabet).shuffle().slice(n).toString();
}
String s = randomStringFromAlphabet("00001111", 4);
/** A list of all valid hexadecimal characters. */
private static char[] HEX_VALUES = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F' };
/** Random number generator to be used to create random chars. */
private static Random RANDOM = new SecureRandom();
/**
* Creates a number of random hexadecimal characters.
*
* @param nValues the amount of characters to generate
*
* @return an array containing <code>nValues</code> hex chars
*/
public static char[] createRandomHexValues(int nValues) {
char[] ret = new char[nValues];
for (int i = 0; i < nValues; i++) {
ret[i] = HEX_VALUES[RANDOM.nextInt(HEX_VALUES.length)];
}
return ret;
}
If you don't mind adding a new library in your code you can generate characters with MockNeat (disclaimer: I am one of the authors).
MockNeat mock = MockNeat.threadLocal();
Character chr = mock.chars().val();
Character lowerLetter = mock.chars().lowerLetters().val();
Character upperLetter = mock.chars().upperLetters().val();
Character digit = mock.chars().digits().val();
Character hex = mock.chars().hex().val();
My propose for generating random string with mixed case like: "DthJwMvsTyu".
This algorithm based on ASCII codes of letters when its codes a-z (97 to 122) and A-Z (65 to 90) differs in 5th bit (2^5 or 1 << 5 or 32).
random.nextInt(2): result is 0 or 1.
random.nextInt(2) << 5: result is 0 or 32.
Upper A is 65 and lower a is 97. Difference is only on 5th bit (32) so for generating random char we do binary OR '|' random charCaseBit (0 or 32) and random code from A to Z (65 to 90).
public String fastestRandomStringWithMixedCase(int length) {
Random random = new Random();
final int alphabetLength = 'Z' - 'A' + 1;
StringBuilder result = new StringBuilder(length);
while (result.length() < length) {
final char charCaseBit = (char) (random.nextInt(2) << 5);
result.append((char) (charCaseBit | ('A' + random.nextInt(alphabetLength))));
}
return result.toString();
}
Here is the code to generate random alphanumeric code. First you have to declare a string of allowed characters what you want to include in random number.and also define max length of string
SecureRandom secureRandom = new SecureRandom();
String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
StringBuilder generatedString= new StringBuilder();
for (int i = 0; i < MAXIMUM_LENGTH; i++) {
int randonSequence = secureRandom .nextInt(CHARACTERS.length());
generatedString.append(CHARACTERS.charAt(randonSequence));
}
Use toString() method to get String from StringBuilder
This is a simple but useful discovery. It defines a class named RandomCharacter with 5 overloaded methods to get a certain type of character randomly. You can use these methods in your future projects.
public class RandomCharacter {
/** Generate a random character between ch1 and ch2 */
public static char getRandomCharacter(char ch1, char ch2) {
return (char) (ch1 + Math.random() * (ch2 - ch1 + 1));
}
/** Generate a random lowercase letter */
public static char getRandomLowerCaseLetter() {
return getRandomCharacter('a', 'z');
}
/** Generate a random uppercase letter */
public static char getRandomUpperCaseLetter() {
return getRandomCharacter('A', 'Z');
}
/** Generate a random digit character */
public static char getRandomDigitCharacter() {
return getRandomCharacter('0', '9');
}
/** Generate a random character */
public static char getRandomCharacter() {
return getRandomCharacter('\u0000', '\uFFFF');
}
}
To demonstrate how it works let's have a look at the following test program displaying 175 random lowercase letters.
public class TestRandomCharacter {
/** Main method */
public static void main(String[] args) {
final int NUMBER_OF_CHARS = 175;
final int CHARS_PER_LINE = 25;
// Print random characters between 'a' and 'z', 25 chars per line
for (int i = 0; i < NUMBER_OF_CHARS; i++) {
char ch = RandomCharacter.getRandomLowerCaseLetter();
if ((i + 1) % CHARS_PER_LINE == 0)
System.out.println(ch);
else
System.out.print(ch);
}
}
}
Note: If you are unfamiliar with overloaded methhods, in a nutshell Method Overloading is a feature that allows a class to have more than one method having the same name, if their argument lists are different.
In fact mentioned methods don't generate real random char. To generate real random char you should give it a random seed! in example time in millisecond. this code generate 10 random char and then Convert it to String:
import java.util.Random;
public class MyClass {
public static void main() {
String randomKey;
char[] tempArray={0,0,0,0,0,0,0,0,0,0}; //ten characters
long seed=System.currentTimeMillis();
Random random=new Random(seed);
for (int aux=0; aux<10;aux++){
tempArray[aux]=(char) random.nextInt(255);
System.out.println(tempArray[aux]);
}
randomKey=String.copyValueOf(tempArray);
System.out.println(randomKey);
}
}
public static void main(String[] args) {
// System.out.println("Enter a number to changeit at char ");
Random random = new Random();
int x = random.nextInt(26)+65; //0 to 25
System.out.println((char)x);
}
java.util.Random is the more effective one I have tried out so far, having a precision of 98.65% uniqueness.
I have provided bellow some tests which generate 10000 batches of a hundred 2 alphanumeric chars strings and calculates the average.
Other random tools were RandomStringUtils from commons.lang3 and java.util.Math.
public static void main(String[] args) {
int unitPrintMarksTotal = 0;
for (int i = 0; i < 10000; i++) {
unitPrintMarksTotal += generateBatchOfUniquePrintMarks(i);
}
System.out.println("The precision across 10000 runs with 100 item batches is: " + (float) unitPrintMarksTotal / 10000);
}
private static int generateBatchOfUniquePrintMarks(int batch) {
Set<String> printMarks = new HashSet<>();
for (int i = 0; i < 100; i++) {
printMarks.add(generatePrintMarkWithJavaUtil());
}
System.out.println("Batch " + batch + " Unique number of elements is " + printMarks.size());
return printMarks.size();
}
// the best so far => 98.65
// with 3 chars => 99.98
// with 4 chars => 99.9997
private static String generatePrintMarkWithJavaUtil() {
int leftLimit = 48; // numeral '0'
int rightLimit = 122; // letter 'z'
int targetStringLength = 2;
String printMark;
do {
printMark = new Random().ints(leftLimit, rightLimit + 1)
.filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
.limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
} while (!isValid(printMark));
return printMark;
}
// 95.46
private static String generatePrintMarkWithCommonsLang3() {
String printMark;
do {
printMark = RandomStringUtils.randomAlphanumeric(2).toUpperCase();
} while (!isValid(printMark));
return printMark;
}
// 95.92
private static String generatePrintMarkWithMathRandom() {
final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder printMark;
do {
printMark = new StringBuilder();
int i = (int) (Math.random() * ALPHA_NUMERIC_STRING.length());
printMark.append(ALPHA_NUMERIC_STRING.charAt(i));
int j = (int) (Math.random() * ALPHA_NUMERIC_STRING.length());
printMark.append(ALPHA_NUMERIC_STRING.charAt(j));
} while (!isValid(printMark.toString()));
return printMark.toString();
}
private static boolean isValid(final String printMark) {
return true;
}