fix methods

This commit is contained in:
Looly
2026-01-23 11:42:57 +08:00
parent ce77e50411
commit c860c6e704
22 changed files with 152 additions and 74 deletions

View File

@@ -1,19 +1,3 @@
/*
* Copyright (c) 2013-2026 Hutool Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hutool.v7.core.util;
import cn.hutool.v7.core.array.ArrayUtil;
@@ -46,19 +30,27 @@ public class RandomUtil {
/**
* 用于随机选的数字
*/
public static final String BASE_NUMBER = "0123456789";
public static final String NUMBERS = "0123456789";
/**
* 用于随机选的字符
* 用于随机选的大写字符
*/
public static final String BASE_CHAR = "abcdefghijklmnopqrstuvwxyz";
public static final String LETTERS_UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 用于随机选的小写字符
*/
public static final String LETTERS_LOWER = "abcdefghijklmnopqrstuvwxyz";
/**
* 用于随机选的字符(包含大写和小写)
*/
public static final String LETTERS = LETTERS_UPPER + LETTERS_LOWER;
/**
* 用于随机选的字符和数字(小写)
*/
public static final String BASE_CHAR_NUMBER_LOWER = BASE_CHAR + BASE_NUMBER;
public static final String LETTERS_NUMBERS_LOWER = LETTERS_LOWER + NUMBERS;
/**
* 用于随机选的字符和数字(包括大写和小写字母)
*/
public static final String BASE_CHAR_NUMBER = BASE_CHAR.toUpperCase() + BASE_CHAR_NUMBER_LOWER;
public static final String LETTERS_NUMBERS = LETTERS + NUMBERS;
// region ----- get or create Random
@@ -216,6 +208,7 @@ public class RandomUtil {
* @return 随机的汉字字符
* @since 5.7.15
*/
@SuppressWarnings("UnnecessaryUnicodeEscape")
public static char randomChinese() {
return (char) randomInt('\u4E00', '\u9FFF');
}
@@ -654,8 +647,8 @@ public class RandomUtil {
* @param length 字符串的长度
* @return 随机字符串
*/
public static String randomString(final int length) {
return randomString(BASE_CHAR_NUMBER, length);
public static String randomLettersAndNumbers(final int length) {
return randomString(LETTERS_NUMBERS, length);
}
/**
@@ -664,8 +657,8 @@ public class RandomUtil {
* @param length 字符串的长度
* @return 随机字符串
*/
public static String randomStringLower(final int length) {
return randomString(BASE_CHAR_NUMBER_LOWER, length);
public static String randomLettersAndNumbersLower(final int length) {
return randomString(LETTERS_NUMBERS_LOWER, length);
}
/**
@@ -675,8 +668,8 @@ public class RandomUtil {
* @return 随机字符串
* @since 4.0.13
*/
public static String randomStringUpper(final int length) {
return randomString(BASE_CHAR_NUMBER_LOWER, length).toUpperCase();
public static String randomLettersAndNumbersUpper(final int length) {
return randomString(LETTERS_NUMBERS_LOWER, length).toUpperCase();
}
/**
@@ -686,8 +679,8 @@ public class RandomUtil {
* @param elemData 要排除的字符串,如去重容易混淆的字符串oO0、lL1、q9Q、pP区分大小写
* @return 随机字符串
*/
public static String randomStringWithoutStr(final int length, final String elemData) {
String baseStr = BASE_CHAR_NUMBER;
public static String randomLettersAndNumbersWithoutStr(final int length, final String elemData) {
String baseStr = LETTERS_NUMBERS;
baseStr = StrUtil.removeAll(baseStr, elemData.toCharArray());
return randomString(baseStr, length);
}
@@ -700,8 +693,8 @@ public class RandomUtil {
* @return 随机字符串
* @since 5.8.28
*/
public static String randomStringLowerWithoutStr(final int length, final String elemData) {
String baseStr = BASE_CHAR_NUMBER_LOWER;
public static String randomLettersAndNumbersLowerWithoutStr(final int length, final String elemData) {
String baseStr = LETTERS_NUMBERS_LOWER;
baseStr = StrUtil.removeAll(baseStr, elemData.toLowerCase().toCharArray());
return randomString(baseStr, length);
}
@@ -713,7 +706,37 @@ public class RandomUtil {
* @return 随机字符串
*/
public static String randomNumbers(final int length) {
return randomString(BASE_NUMBER, length);
return randomString(NUMBERS, length);
}
/**
* 获得一个随机只包含字母的字符串
*
* @param length 字符串的长度
* @return 随机字符串
*/
public static String randomLetters(final int length) {
return randomString(LETTERS, length);
}
/**
* 获得一个只包含小写字母的字符串
*
* @param length 字符串的长度
* @return 随机字符串
*/
public static String randomLettersLower(final int length) {
return randomString(LETTERS_LOWER, length);
}
/**
* 获得一个只包含大写字母的随机字符串
*
* @param length 随机字符串的长度
* @return 随机字符串
*/
public static String randomLettersUpper(final int length) {
return randomString(LETTERS_UPPER, length);
}
/**
@@ -750,7 +773,7 @@ public class RandomUtil {
* @since 3.1.2
*/
public static char randomNumber() {
return randomChar(BASE_NUMBER);
return randomChar(NUMBERS);
}
/**
@@ -760,7 +783,7 @@ public class RandomUtil {
* @since 3.1.2
*/
public static char randomChar() {
return randomChar(BASE_CHAR_NUMBER_LOWER);
return randomChar(LETTERS_NUMBERS_LOWER);
}
/**
@@ -834,4 +857,4 @@ public class RandomUtil {
return DateUtil.offset(baseDate, dateField, randomInt(min, max));
}
// endregion
}
}

View File

@@ -41,7 +41,7 @@ public class LRUCacheTest {
final LRUCache<String, String> cache = CacheUtil.newLRUCache(100, 10);
for (int i = 0; i < 10000; i++) {
//ThreadUtil.execute(()-> cache.put(RandomUtil.randomString(5), "1243", 10));
ThreadUtil.execute(()-> cache.get(RandomUtil.randomStringLower(5), ()->RandomUtil.randomStringLower(10)));
ThreadUtil.execute(()-> cache.get(RandomUtil.randomLettersAndNumbersLower(5), ()->RandomUtil.randomLettersAndNumbersLower(10)));
}
ThreadUtil.sleep(3000);
}

View File

@@ -53,7 +53,7 @@ public class Base32Test {
@Test
public void encodeAndDecodeRandomTest(){
final String a = RandomUtil.randomStringLower(RandomUtil.randomInt(1000));
final String a = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(1000));
final String encode = Base32.encode(a);
final String decodeStr = Base32.decodeStr(encode);
Assertions.assertEquals(a, decodeStr);

View File

@@ -50,7 +50,7 @@ public class Base62Test {
@Test
public void encodeAndDecodeRandomTest() {
final String a = RandomUtil.randomStringLower(RandomUtil.randomInt(1000));
final String a = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(1000));
final String encode = Base62.encode(a);
final String decodeStr = Base62.decodeStr(encode);
Assertions.assertEquals(a, decodeStr);
@@ -58,7 +58,7 @@ public class Base62Test {
@Test
public void encodeAndDecodeInvertedRandomTest() {
final String a = RandomUtil.randomStringLower(RandomUtil.randomInt(1000));
final String a = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(1000));
final String encode = Base62.encodeInverted(a);
final String decodeStr = Base62.decodeStrInverted(encode);
Assertions.assertEquals(a, decodeStr);

View File

@@ -32,7 +32,7 @@ public class Base64Test {
@Test
public void isTypeBase64Test(){
Assertions.assertTrue(Base64.isTypeBase64(Base64.encode(RandomUtil.randomStringLower(1000))));
Assertions.assertTrue(Base64.isTypeBase64(Base64.encode(RandomUtil.randomLettersAndNumbersLower(1000))));
}
@Test

View File

@@ -105,7 +105,7 @@ public class MetroHashTest {
final String[] result = new String[10000000];
int index = 0;
while (index < 10000000) {
result[index++] = RandomUtil.randomStringLower(RandomUtil.randomInt(64));
result[index++] = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(64));
}
return result;
}

View File

@@ -27,10 +27,10 @@ public class MemorySafeLinkedBlockingQueueTest {
public void offerTest(){
// 设置初始值达到最大,这样任何时候元素都无法加入队列
final MemorySafeLinkedBlockingQueue<String> queue = new MemorySafeLinkedBlockingQueue<>(Long.MAX_VALUE);
Assertions.assertFalse(queue.offer(RandomUtil.randomStringLower(RandomUtil.randomInt(100))));
Assertions.assertFalse(queue.offer(RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(100))));
// 设定一个很小的值,可以成功加入
queue.setMaxFreeMemory(10);
Assertions.assertTrue(queue.offer(RandomUtil.randomStringLower(RandomUtil.randomInt(100))));
Assertions.assertTrue(queue.offer(RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(100))));
}
}

View File

@@ -29,7 +29,7 @@ public class InternUtilTest {
@Test
public void weakTest(){
final Intern<String> intern = InternUtil.ofWeak();
final String a1 = RandomUtil.randomStringLower(RandomUtil.randomInt(100));
final String a1 = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(100));
final String a2 = new String(a1);
Assertions.assertNotSame(a1, a2);

View File

@@ -55,6 +55,6 @@ public class TolerantMapTest {
map.put("tuesday", "星期二");
assert "星期二".equals(map.get("tuesday"));
assert "default".equals(map.get(RandomUtil.randomStringLower(6)));
assert "default".equals(map.get(RandomUtil.randomLettersAndNumbersLower(6)));
}
}

View File

@@ -495,7 +495,7 @@ public class StrUtilTest {
@Test
public void briefTest() {
// case: 1 至 str.length - 1
final String str = RandomUtil.randomStringLower(RandomUtil.randomInt(1, 100));
final String str = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(1, 100));
for (int maxLength = 1; maxLength < str.length(); maxLength++) {
final String brief = StrUtil.brief(str, maxLength);
assertEquals(brief.length(), maxLength);

View File

@@ -63,9 +63,9 @@ public class TextSimilarityTest {
@Disabled
void longestCommonSubstringLengthTest() {
// https://github.com/chinabugotech/hutool/issues/3045
final String strCommon = RandomUtil.randomStringLower(1024 * 32);
final String strA = RandomUtil.randomStringLower(1024 * 32) + strCommon;
final String strB = RandomUtil.randomStringLower(1024 * 32) + strCommon;
final String strCommon = RandomUtil.randomLettersAndNumbersLower(1024 * 32);
final String strA = RandomUtil.randomLettersAndNumbersLower(1024 * 32) + strCommon;
final String strB = RandomUtil.randomLettersAndNumbersLower(1024 * 32) + strCommon;
final int i = TextSimilarity.longestCommonSubstringLength(strA, strB);
Console.log(i);

View File

@@ -28,25 +28,28 @@ import java.math.RoundingMode;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.*;
public class RandomUtilTest {
@Test
public void randomEleSetTest(){
final Set<Integer> set = RandomUtil.randomEleSet(ListUtil.of(1, 2, 3, 4, 5, 6), 2);
Assertions.assertEquals(2, set.size());
assertEquals(2, set.size());
}
@Test
public void randomElesTest(){
final List<Integer> result = RandomUtil.randomEles(ListUtil.of(1, 2, 3, 4, 5, 6), 2);
Assertions.assertEquals(2, result.size());
assertEquals(2, result.size());
}
@Test
public void randomDoubleTest() {
final double randomDouble = RandomUtil.randomDouble(0, 1, 0, RoundingMode.HALF_UP);
Assertions.assertTrue(randomDouble <= 1);
assertTrue(randomDouble <= 1);
}
@Test
@@ -58,31 +61,31 @@ public class RandomUtilTest {
@Test
public void randomNumberTest() {
final char c = RandomUtil.randomNumber();
Assertions.assertTrue(c <= '9');
assertTrue(c <= '9');
}
@Test
public void randomIntTest() {
final int c = RandomUtil.randomInt(10, 100);
Assertions.assertTrue(c >= 10 && c < 100);
assertTrue(c >= 10 && c < 100);
}
@Test
public void randomBytesTest() {
final byte[] c = RandomUtil.randomBytes(10);
Assertions.assertNotNull(c);
assertNotNull(c);
}
@Test
public void randomChineseTest(){
final char c = RandomUtil.randomChinese();
Assertions.assertTrue(c > 0);
assertTrue(c > 0);
}
@Test
public void randomStringLowerWithoutStrTest() {
public void randomLettersAndNumbersLowerWithoutStrTest() {
for (int i = 0; i < 100; i++) {
final String s = RandomUtil.randomStringLowerWithoutStr(8, "0IPOL");
final String s = RandomUtil.randomLettersAndNumbersLowerWithoutStr(8, "0IPOL");
for (final char c : "0IPOL".toCharArray()) {
Assertions.assertFalse(s.contains((String.valueOf(c).toLowerCase(Locale.ROOT))));
}
@@ -92,14 +95,66 @@ public class RandomUtilTest {
@Test
public void randomStringOfLengthTest(){
final String s = RandomUtil.randomString("123", -1);
Assertions.assertNotNull(s);
assertNotNull(s);
}
@Test
public void generateRandomNumberTest(){
final int[] ints = RandomUtil.randomPickInts(5, NumberUtil.range(5, 20));
Assertions.assertEquals(5, ints.length);
assertEquals(5, ints.length);
final Set<?> set = ConvertUtil.convert(Set.class, ints);
Assertions.assertEquals(5, set.size());
assertEquals(5, set.size());
}
/**
* 测试生成指定长度的数字字符串
*/
@Test
public void randomNumbersTest() {
// 测试生成长度为5的数字字符串
final String result1 = RandomUtil.randomNumbers(5);
assertEquals(5, result1.length(), "生成的字符串长度应该等于指定长度");
assertTrue(isNumeric(result1), "生成的字符串应该只包含数字");
// 测试生成长度为10的数字字符串
final String result2 = RandomUtil.randomNumbers(10);
assertEquals(10, result2.length(), "生成的字符串长度应该等于指定长度");
assertTrue(isNumeric(result2), "生成的字符串应该只包含数字");
// 测试生成长度为1的数字字符串
final String result3 = RandomUtil.randomNumbers(1);
assertEquals(1, result3.length(), "生成的字符串长度应该等于指定长度");
assertTrue(isNumeric(result3), "生成的字符串应该只包含数字");
// 测试生成长度为0的数字字符串会被调整为1
final String result4 = RandomUtil.randomNumbers(0);
assertEquals(1, result4.length(), "当长度为0时应生成长度为1的字符串");
assertTrue(isNumeric(result4), "生成的字符串应该只包含数字");
// 测试生成长度为负数的数字字符串会被调整为1
final String result5 = RandomUtil.randomNumbers(-5);
assertEquals(1, result5.length(), "当长度为负数时应生成长度为1的字符串");
assertTrue(isNumeric(result5), "生成的字符串应该只包含数字");
// 验证多次生成的结果都不相同(概率性验证)
final String result6 = RandomUtil.randomNumbers(8);
final String result7 = RandomUtil.randomNumbers(8);
// 由于是随机生成,不能保证一定不同,但大部分情况下应该不同
// 所以我们主要验证它们都符合预期格式
assertEquals(8, result6.length(), "生成的字符串长度应该等于指定长度");
assertTrue(isNumeric(result6), "生成的字符串应该只包含数字");
assertEquals(8, result7.length(), "生成的字符串长度应该等于指定长度");
assertTrue(isNumeric(result7), "生成的字符串应该只包含数字");
}
/**
* 辅助方法:检查字符串是否只包含数字
*/
private boolean isNumeric(final String str) {
if (str == null || str.isEmpty()) {
return false;
}
final Pattern pattern = Pattern.compile("\\d+");
return pattern.matcher(str).matches();
}
}

View File

@@ -192,7 +192,7 @@ public class KeyUtil {
}
if (null == password) {
password = RandomUtil.randomStringLower(32).toCharArray();
password = RandomUtil.randomLettersAndNumbersLower(32).toCharArray();
}
return generateKey(algorithm, SpecUtil.createPBEKeySpec(password));
}

View File

@@ -81,7 +81,7 @@ public class SpecUtil {
*/
public static PBEKeySpec createPBEKeySpec(char[] password) {
if (null == password) {
password = RandomUtil.randomStringLower(32).toCharArray();
password = RandomUtil.randomLettersAndNumbersLower(32).toCharArray();
}
return new PBEKeySpec(password);
}

View File

@@ -152,7 +152,7 @@ public class SymmetricTest {
@Test
public void aesZeroPaddingTest() {
final String content = RandomUtil.randomStringLower(RandomUtil.randomInt(200));
final String content = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(200));
final AES aes = new AES(Mode.CBC, Padding.ZeroPadding, "0123456789ABHAEQ".getBytes(), "DYgjCEIMVrj2W9xN".getBytes());
// 加密为16进制表示
@@ -178,7 +178,7 @@ public class SymmetricTest {
@Test
public void aesPkcs7PaddingTest() {
final String content = RandomUtil.randomStringLower(RandomUtil.randomInt(200));
final String content = RandomUtil.randomLettersAndNumbersLower(RandomUtil.randomInt(200));
final AES aes = new AES("CBC", "PKCS7Padding",
RandomUtil.randomBytes(32),
"DYgjCEIMVrj2W9xN".getBytes());

View File

@@ -29,7 +29,7 @@ public class ZucTest {
final byte[] iv = RandomUtil.randomBytes(16);
final ZUC zuc = new ZUC(ZUC.ZUCAlgorithm.ZUC_128, secretKey, iv);
final String msg = RandomUtil.randomStringLower(500);
final String msg = RandomUtil.randomLettersAndNumbersLower(500);
final byte[] crypt2 = zuc.encrypt(msg);
final String msg2 = zuc.decryptStr(crypt2, CharsetUtil.UTF_8);
Assertions.assertEquals(msg, msg2);
@@ -41,7 +41,7 @@ public class ZucTest {
final byte[] iv = RandomUtil.randomBytes(25);
final ZUC zuc = new ZUC(ZUC.ZUCAlgorithm.ZUC_256, secretKey, iv);
final String msg = RandomUtil.randomStringLower(500);
final String msg = RandomUtil.randomLettersAndNumbersLower(500);
final byte[] crypt2 = zuc.encrypt(msg);
final String msg2 = zuc.decryptStr(crypt2, CharsetUtil.UTF_8);
Assertions.assertEquals(msg, msg2);

View File

@@ -189,8 +189,8 @@ public class DbTest {
private Entity buildEntity() {
final Entity entity = Entity.of("act_ge_property");
entity.put("NAME_", RandomUtil.randomString(15));
entity.put("VALUE_", RandomUtil.randomString(50));
entity.put("NAME_", RandomUtil.randomLettersAndNumbers(15));
entity.put("VALUE_", RandomUtil.randomLettersAndNumbers(50));
entity.put("REV_", RandomUtil.randomInt());
return entity;
}

View File

@@ -63,6 +63,6 @@ public class DriverUtilTest {
map.put("jdbc:goldendb:", "com.goldendb.jdbc.Driver");
map.forEach((k, v) -> Assertions.assertEquals(v,
DriverUtil.identifyDriver(k + RandomUtil.randomStringLower(2))));
DriverUtil.identifyDriver(k + RandomUtil.randomLettersAndNumbersLower(2))));
}
}

View File

@@ -41,7 +41,7 @@ public class HttpGlobalConfig implements Serializable {
* 底层调用:{@link HttpURLConnection#setConnectTimeout(int)} 同时设置: 连接超时
*/
private static int timeout = -1;
private static String boundary = "--------------------Hutool_" + RandomUtil.randomStringLower(16);
private static String boundary = "--------------------Hutool_" + RandomUtil.randomLettersAndNumbersLower(16);
private static int maxRedirects = 0;
private static boolean ignoreEOFError = true;
/**

View File

@@ -53,7 +53,7 @@ public class JsonAddJmh {
Console.log("准备数据。。。");
testData = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
testData.add(RandomUtil.randomString(20));
testData.add(RandomUtil.randomLettersAndNumbers(20));
}
hutoolJSON = new JSONArray();

View File

@@ -51,7 +51,7 @@ public class JsonPutJmh {
public void setup() {
testData = new HashMap<>(100, 1);
for (int i = 0; i < 100; i++) {
testData.put(RandomUtil.randomString(10), RandomUtil.randomString(20));
testData.put(RandomUtil.randomLettersAndNumbers(10), RandomUtil.randomLettersAndNumbers(20));
}
hutoolJSON = new JSONObject();

View File

@@ -42,7 +42,7 @@ public abstract class AbstractGenerator implements CodeGenerator {
* @param count 生成验证码长度
*/
public AbstractGenerator(final int count) {
this(RandomUtil.BASE_CHAR_NUMBER_LOWER, count);
this(RandomUtil.LETTERS_NUMBERS_LOWER, count);
}
/**