mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add NanoId
This commit is contained in:
parent
6ebd912062
commit
f9b29c5f2a
@ -8,6 +8,7 @@
|
|||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【core 】 DateUtil增加ceiling重载,可选是否归零毫秒
|
* 【core 】 DateUtil增加ceiling重载,可选是否归零毫秒
|
||||||
* 【core 】 IterUtil增加firstMatch方法
|
* 【core 】 IterUtil增加firstMatch方法
|
||||||
|
* 【core 】 增加NanoId
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【core 】 修复FileUtil.normalize处理上级路径的问题(issue#I3YPEH@Gitee)
|
* 【core 】 修复FileUtil.normalize处理上级路径的问题(issue#I3YPEH@Gitee)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package cn.hutool.core.lang;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for generating unique String IDs.
|
|
||||||
*
|
|
||||||
* The implementations of the core logic in this class are based on NanoId, a JavaScript
|
|
||||||
* library by Andrey Sitnik released under the MIT license. (https://github.com/ai/nanoid)
|
|
||||||
*
|
|
||||||
* @author David Klebanoff
|
|
||||||
*/
|
|
||||||
public final class NanoId {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>NanoIdUtils</code> instances should NOT be constructed in standard programming.
|
|
||||||
* Instead, the class should be used as <code>NanoIdUtils.randomNanoId();</code>.
|
|
||||||
*/
|
|
||||||
private NanoId() {
|
|
||||||
//Do Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default random number generator used by this class.
|
|
||||||
* Creates cryptographically strong NanoId Strings.
|
|
||||||
*/
|
|
||||||
public static final SecureRandom DEFAULT_NUMBER_GENERATOR = new SecureRandom();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default alphabet used by this class.
|
|
||||||
* Creates url-friendly NanoId Strings using 64 unique symbols.
|
|
||||||
*/
|
|
||||||
public static final char[] DEFAULT_ALPHABET =
|
|
||||||
"_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default size used by this class.
|
|
||||||
* Creates NanoId Strings with slightly more unique values than UUID v4.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_SIZE = 21;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static factory to retrieve a url-friendly, pseudo randomly generated, NanoId String.
|
|
||||||
*
|
|
||||||
* The generated NanoId String will have 21 symbols.
|
|
||||||
*
|
|
||||||
* The NanoId String is generated using a cryptographically strong pseudo random number
|
|
||||||
* generator.
|
|
||||||
*
|
|
||||||
* @return A randomly generated NanoId String.
|
|
||||||
*/
|
|
||||||
public static String randomNanoId() {
|
|
||||||
return randomNanoId(DEFAULT_NUMBER_GENERATOR, DEFAULT_ALPHABET, DEFAULT_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static factory to retrieve a NanoId String.
|
|
||||||
*
|
|
||||||
* The string is generated using the given random number generator.
|
|
||||||
*
|
|
||||||
* @param random The random number generator.
|
|
||||||
* @param alphabet The symbols used in the NanoId String.
|
|
||||||
* @param size The number of symbols in the NanoId String.
|
|
||||||
* @return A randomly generated NanoId String.
|
|
||||||
*/
|
|
||||||
public static String randomNanoId(final Random random, final char[] alphabet, final int size) {
|
|
||||||
|
|
||||||
if (random == null) {
|
|
||||||
throw new IllegalArgumentException("random cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alphabet == null) {
|
|
||||||
throw new IllegalArgumentException("alphabet cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alphabet.length == 0 || alphabet.length >= 256) {
|
|
||||||
throw new IllegalArgumentException("alphabet must contain between 1 and 255 symbols.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size <= 0) {
|
|
||||||
throw new IllegalArgumentException("size must be greater than zero.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int mask = (2 << (int) Math.floor(Math.log(alphabet.length - 1) / Math.log(2))) - 1;
|
|
||||||
final int step = (int) Math.ceil(1.6 * mask * size / alphabet.length);
|
|
||||||
|
|
||||||
final StringBuilder idBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
final byte[] bytes = new byte[step];
|
|
||||||
random.nextBytes(bytes);
|
|
||||||
for (int i = 0; i < step; i++) {
|
|
||||||
final int alphabetIndex = bytes[i] & mask;
|
|
||||||
if (alphabetIndex < alphabet.length) {
|
|
||||||
idBuilder.append(alphabet[alphabetIndex]);
|
|
||||||
if (idBuilder.length() == size) {
|
|
||||||
return idBuilder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
103
hutool-core/src/main/java/cn/hutool/core/lang/id/NanoId.java
Normal file
103
hutool-core/src/main/java/cn/hutool/core/lang/id/NanoId.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package cn.hutool.core.lang.id;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NanoId,一个小型、安全、对 URL友好的唯一字符串 ID 生成器,特点:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>安全:它使用加密、强大的随机 API,并保证符号的正确分配</li>
|
||||||
|
* <li>体积小:只有 258 bytes 大小(压缩后)、无依赖</li>
|
||||||
|
* <li>紧凑:它使用比 UUID (A-Za-z0-9_~)更多的符号</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此实现的逻辑基于JavaScript的NanoId实现,见:https://github.com/ai/nanoid
|
||||||
|
*
|
||||||
|
* @author David Klebanoff
|
||||||
|
*/
|
||||||
|
public class NanoId {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认随机数生成器,使用{@link SecureRandom}确保健壮性
|
||||||
|
*/
|
||||||
|
private static final SecureRandom DEFAULT_NUMBER_GENERATOR = RandomUtil.getSecureRandom();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认随机字母表,使用URL安全的Base64字符
|
||||||
|
*/
|
||||||
|
private static final char[] DEFAULT_ALPHABET =
|
||||||
|
"_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认长度
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_SIZE = 21;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成伪随机的NanoId字符串,长度为默认的{@link #DEFAULT_SIZE},使用密码安全的伪随机生成器
|
||||||
|
*
|
||||||
|
* @return 伪随机的NanoId字符串
|
||||||
|
*/
|
||||||
|
public static String randomNanoId() {
|
||||||
|
return randomNanoId(DEFAULT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成伪随机的NanoId字符串
|
||||||
|
*
|
||||||
|
* @param size ID长度
|
||||||
|
* @return 伪随机的NanoId字符串
|
||||||
|
*/
|
||||||
|
public static String randomNanoId(int size) {
|
||||||
|
return randomNanoId(null, null, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成伪随机的NanoId字符串
|
||||||
|
*
|
||||||
|
* @param random 随机数生成器
|
||||||
|
* @param alphabet 随机字母表
|
||||||
|
* @param size ID长度
|
||||||
|
* @return 伪随机的NanoId字符串
|
||||||
|
*/
|
||||||
|
public static String randomNanoId(Random random, char[] alphabet, int size) {
|
||||||
|
if (random == null) {
|
||||||
|
random = DEFAULT_NUMBER_GENERATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alphabet == null) {
|
||||||
|
alphabet = DEFAULT_ALPHABET;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alphabet.length == 0 || alphabet.length >= 256) {
|
||||||
|
throw new IllegalArgumentException("Alphabet must contain between 1 and 255 symbols.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
throw new IllegalArgumentException("Size must be greater than zero.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int mask = (2 << (int) Math.floor(Math.log(alphabet.length - 1) / Math.log(2))) - 1;
|
||||||
|
final int step = (int) Math.ceil(1.6 * mask * size / alphabet.length);
|
||||||
|
|
||||||
|
final StringBuilder idBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
final byte[] bytes = new byte[step];
|
||||||
|
random.nextBytes(bytes);
|
||||||
|
for (int i = 0; i < step; i++) {
|
||||||
|
final int alphabetIndex = bytes[i] & mask;
|
||||||
|
if (alphabetIndex < alphabet.length) {
|
||||||
|
idBuilder.append(alphabet[alphabetIndex]);
|
||||||
|
if (idBuilder.length() == size) {
|
||||||
|
return idBuilder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
hutool-core/src/main/java/cn/hutool/core/lang/id/package-info.java
Executable file
7
hutool-core/src/main/java/cn/hutool/core/lang/id/package-info.java
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* 提供各种ID生成
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 5.7.5
|
||||||
|
*/
|
||||||
|
package cn.hutool.core.lang.id;
|
@ -1,14 +1,13 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.lang.*;
|
import cn.hutool.core.lang.ObjectId;
|
||||||
|
import cn.hutool.core.lang.Singleton;
|
||||||
|
import cn.hutool.core.lang.Snowflake;
|
||||||
|
import cn.hutool.core.lang.UUID;
|
||||||
|
import cn.hutool.core.lang.id.NanoId;
|
||||||
import cn.hutool.core.net.NetUtil;
|
import cn.hutool.core.net.NetUtil;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import static cn.hutool.core.lang.NanoId.DEFAULT_ALPHABET;
|
|
||||||
import static cn.hutool.core.lang.NanoId.DEFAULT_NUMBER_GENERATOR;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID生成器工具类,此工具类中主要封装:
|
* ID生成器工具类,此工具类中主要封装:
|
||||||
*
|
*
|
||||||
@ -241,24 +240,26 @@ public class IdUtil {
|
|||||||
*/
|
*/
|
||||||
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
|
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------- NanoId
|
// ------------------------------------------------------------------- NanoId
|
||||||
/**
|
/**
|
||||||
* 获取随机NanoId
|
* 获取随机NanoId
|
||||||
*
|
*
|
||||||
* @return 随机NanoId
|
* @return 随机NanoId
|
||||||
|
* @since 5.7.5
|
||||||
*/
|
*/
|
||||||
public static String randomNanoId() {
|
public static String nanoId() {
|
||||||
return NanoId.randomNanoId();
|
return NanoId.randomNanoId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static factory to retrieve a NanoId String.
|
* 获取随机NanoId
|
||||||
*
|
*
|
||||||
* The string is generated using the given random number generator.
|
* @param size ID中的字符数量
|
||||||
*
|
* @return 随机NanoId
|
||||||
* @param size The number of symbols in the NanoId String.
|
* @since 5.7.5
|
||||||
* @return A randomly generated NanoId String.
|
|
||||||
*/
|
*/
|
||||||
public static String randomNanoId(final int size){
|
public static String nanoId(int size){
|
||||||
return NanoId.randomNanoId(DEFAULT_NUMBER_GENERATOR, DEFAULT_ALPHABET, size);
|
return NanoId.randomNanoId(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package cn.hutool.core.lang;
|
package cn.hutool.core.lang;
|
||||||
|
|
||||||
import org.hamcrest.MatcherAssert;
|
import cn.hutool.core.lang.id.NanoId;
|
||||||
import org.hamcrest.Matchers;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.results.ResultMatchers;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -20,31 +17,15 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for NanoIdUtils.
|
* Tests for NanoId.
|
||||||
*
|
*
|
||||||
* @author David Klebanoff
|
* @author David Klebanoff, Looly
|
||||||
* @see NanoId
|
* @see NanoId
|
||||||
*/
|
*/
|
||||||
public class NanoIdTest {
|
public class NanoIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void NanoId_VerifyClassIsFinal_Verified() {
|
public void nanoIdVerify100KRandomNanoIdsAreUniqueVerifiedTest() {
|
||||||
if ((NanoId.class.getModifiers() & Modifier.FINAL) != Modifier.FINAL) {
|
|
||||||
fail("The class is not final");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NanoId_VerifyConstructorsArePrivate_Verified() {
|
|
||||||
for (final Constructor<?> constructor : NanoId.class.getConstructors()) {
|
|
||||||
if ((constructor.getModifiers() & Modifier.PRIVATE) != Modifier.PRIVATE) {
|
|
||||||
fail("The class has a non-private constructor.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NanoId_Verify100KRandomNanoIdsAreUnique_Verified() {
|
|
||||||
|
|
||||||
//It's not much, but it's a good sanity check I guess.
|
//It's not much, but it's a good sanity check I guess.
|
||||||
final int idCount = 100000;
|
final int idCount = 100000;
|
||||||
@ -62,7 +43,7 @@ public class NanoIdTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void NanoId_SeededRandom_Success() {
|
public void nanoIdSeededRandomSuccessTest() {
|
||||||
|
|
||||||
//With a seed provided, we can know which IDs to expect, and subsequently verify that the
|
//With a seed provided, we can know which IDs to expect, and subsequently verify that the
|
||||||
// provided random number generator is being used as expected.
|
// provided random number generator is being used as expected.
|
||||||
@ -84,7 +65,7 @@ public class NanoIdTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void NanoId_VariousAlphabets_Success() {
|
public void nanoIdVariousAlphabetsSuccessTest() {
|
||||||
|
|
||||||
//Test ID generation with various alphabets consisting of 1 to 255 unique symbols.
|
//Test ID generation with various alphabets consisting of 1 to 255 unique symbols.
|
||||||
for (int symbols = 1; symbols <= 255; symbols++) {
|
for (int symbols = 1; symbols <= 255; symbols++) {
|
||||||
@ -95,8 +76,7 @@ public class NanoIdTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String id = NanoId
|
final String id = NanoId
|
||||||
.randomNanoId(NanoId.DEFAULT_NUMBER_GENERATOR, alphabet,
|
.randomNanoId(null, alphabet, NanoId.DEFAULT_SIZE);
|
||||||
NanoId.DEFAULT_SIZE);
|
|
||||||
|
|
||||||
//Create a regex pattern that only matches to the characters in the alphabet
|
//Create a regex pattern that only matches to the characters in the alphabet
|
||||||
final StringBuilder patternBuilder = new StringBuilder();
|
final StringBuilder patternBuilder = new StringBuilder();
|
||||||
@ -112,13 +92,12 @@ public class NanoIdTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void NanoId_VariousSizes_Success() {
|
public void nanoIdVariousSizesSuccessTest() {
|
||||||
|
|
||||||
//Test ID generation with all sizes between 1 and 1,000.
|
//Test ID generation with all sizes between 1 and 1,000.
|
||||||
for (int size = 1; size <= 1000; size++) {
|
for (int size = 1; size <= 1000; size++) {
|
||||||
|
|
||||||
final String id = NanoId.randomNanoId(NanoId.DEFAULT_NUMBER_GENERATOR,
|
final String id = NanoId.randomNanoId(size);
|
||||||
NanoId.DEFAULT_ALPHABET, size);
|
|
||||||
|
|
||||||
assertEquals(size, id.length());
|
assertEquals(size, id.length());
|
||||||
}
|
}
|
||||||
@ -126,7 +105,7 @@ public class NanoIdTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void NanoId_WellDistributed_Success() {
|
public void nanoIdWellDistributedSuccess() {
|
||||||
|
|
||||||
//Test if symbols in the generated IDs are well distributed.
|
//Test if symbols in the generated IDs are well distributed.
|
||||||
|
|
||||||
@ -139,7 +118,7 @@ public class NanoIdTest {
|
|||||||
for (int i = 0; i < idCount; i++) {
|
for (int i = 0; i < idCount; i++) {
|
||||||
|
|
||||||
final String id = NanoId
|
final String id = NanoId
|
||||||
.randomNanoId(NanoId.DEFAULT_NUMBER_GENERATOR, alphabet, idSize);
|
.randomNanoId(null, alphabet, idSize);
|
||||||
|
|
||||||
for (int j = 0; j < id.length(); j++) {
|
for (int j = 0; j < id.length(); j++) {
|
||||||
final String value = String.valueOf(id.charAt(j));
|
final String value = String.valueOf(id.charAt(j));
|
||||||
@ -156,28 +135,18 @@ public class NanoIdTest {
|
|||||||
//Verify the distribution of characters is pretty even
|
//Verify the distribution of characters is pretty even
|
||||||
for (final Long charCount : charCounts.values()) {
|
for (final Long charCount : charCounts.values()) {
|
||||||
final double distribution = (charCount * alphabet.length / (double) (idCount * idSize));
|
final double distribution = (charCount * alphabet.length / (double) (idCount * idSize));
|
||||||
MatcherAssert.assertThat(distribution, Matchers.closeTo(1.0, 0.05));
|
Assert.assertTrue(distribution >= 0.95 && distribution <= 1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void randomNanoId_NullRandom_ExceptionThrown() {
|
public void randomNanoIdEmptyAlphabetExceptionThrownTest() {
|
||||||
NanoId.randomNanoId(null, new char[] {'a', 'b', 'c'}, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void randomNanoId_NullAlphabet_ExceptionThrown() {
|
|
||||||
NanoId.randomNanoId(new SecureRandom(), null, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void randomNanoId_EmptyAlphabet_ExceptionThrown() {
|
|
||||||
NanoId.randomNanoId(new SecureRandom(), new char[]{}, 10);
|
NanoId.randomNanoId(new SecureRandom(), new char[]{}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void randomNanoId_256Alphabet_ExceptionThrown() {
|
public void randomNanoId256AlphabetExceptionThrownTest() {
|
||||||
|
|
||||||
//The alphabet is composed of 256 unique characters
|
//The alphabet is composed of 256 unique characters
|
||||||
final char[] largeAlphabet = new char[256];
|
final char[] largeAlphabet = new char[256];
|
||||||
@ -190,12 +159,12 @@ public class NanoIdTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void randomNanoId_NegativeSize_ExceptionThrown() {
|
public void randomNanoIdNegativeSizeExceptionThrown() {
|
||||||
NanoId.randomNanoId(new SecureRandom(), new char[]{'a', 'b', 'c'}, -10);
|
NanoId.randomNanoId(new SecureRandom(), new char[]{'a', 'b', 'c'}, -10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void randomNanoId_ZeroSize_ExceptionThrown() {
|
public void randomNanoIdZeroSizeExceptionThrown() {
|
||||||
NanoId.randomNanoId(new SecureRandom(), new char[]{'a', 'b', 'c'}, 0);
|
NanoId.randomNanoId(new SecureRandom(), new char[]{'a', 'b', 'c'}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
6
pom.xml
6
pom.xml
@ -55,12 +55,6 @@
|
|||||||
<version>${junit.version}</version>
|
<version>${junit.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>java-hamcrest</artifactId>
|
|
||||||
<version>2.0.0.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user