diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java
index 2394a5580b..4bcd9566d0 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java
@@ -208,7 +208,7 @@ public class HexUtil extends Hex {
* @param value float值
* @return 16进制字符串
*/
- public static String toHex(float value) {
+ public static String toHex(final float value) {
return Integer.toHexString(Float.floatToIntBits(value));
}
@@ -218,7 +218,7 @@ public class HexUtil extends Hex {
* @param value 16进制字符串
* @return 16进制字符串float值
*/
- public static float hexToFloat(String value) {
+ public static float hexToFloat(final String value) {
return Float.intBitsToFloat(Integer.parseUnsignedInt(removeHexPrefix(value), 16));
}
@@ -228,7 +228,7 @@ public class HexUtil extends Hex {
* @param value double值
* @return 16进制字符串
*/
- public static String toHex(double value) {
+ public static String toHex(final double value) {
return Long.toHexString(Double.doubleToLongBits(value));
}
@@ -238,7 +238,7 @@ public class HexUtil extends Hex {
* @param value 16进制字符串
* @return 16进制字符串double值
*/
- public static double hexToDouble(String value) {
+ public static double hexToDouble(final String value) {
return Double.longBitsToDouble(Long.parseUnsignedLong(removeHexPrefix(value), 16));
}
@@ -288,7 +288,7 @@ public class HexUtil extends Hex {
*
*
* @param hexStr Hex字符串
- * @param prefix 自定义前缀,如0x
+ * @param prefix 自定义前缀,如0x,此前缀每个16进制数前都添加
* @return 格式化后的字符串
*/
public static String format(final String hexStr, final String prefix) {
diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/CityHash.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/CityHash.java
index ea4d4c560c..082bf23eaf 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/CityHash.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/CityHash.java
@@ -26,8 +26,8 @@ import java.util.Arrays;
* 它们分别根据字串计算 64 和 128 位的散列值。这些算法不适用于加密,但适合用在散列表等处。
*
*
- * 代码来自:https://github.com/rolandhe/string-tools
- * 原始算法:https://github.com/google/cityhash
+ * 代码来自:string-tools
+ * 原始算法:cityhash
*
* @author hexiufeng
* @since 5.2.5
diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/AbstractMetroHash.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/AbstractMetroHash.java
index 15563d925f..7b9b36a63a 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/AbstractMetroHash.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/AbstractMetroHash.java
@@ -23,9 +23,9 @@ import java.nio.ByteBuffer;
* 除了卓越的性能外,他们还以算法生成而著称。
*
*
- * 官方实现:https://github.com/jandrewrogers/MetroHash
- * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/
- * 来自:https://github.com/postamar/java-metrohash/
+ * 官方实现:MetroHash
+ * 官方文档:metrohash
+ * 来自:java-metrohash
*
* @author Marius Posta
* @param 返回值类型,为this类型
diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash.java
index da2c3c0353..60e94c1b95 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash.java
@@ -24,9 +24,9 @@ import java.nio.ByteOrder;
* 除了卓越的性能外,他们还以算法生成而著称。
*
*
- * 官方实现:https://github.com/jandrewrogers/MetroHash
- * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/
- * 来自:https://github.com/postamar/java-metrohash/
+ * 官方实现:MetroHash
+ * 官方文档:metrohash
+ * 来自:java-metrohash
*
* @param 返回值类型,为this类型
* @author Marius Posta
diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash128.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash128.java
index 3d38fbbff4..d5f764c601 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash128.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash128.java
@@ -27,9 +27,10 @@ import java.nio.ByteOrder;
* 除了卓越的性能外,他们还以算法生成而著称。
*
*
- * 官方实现:https://github.com/jandrewrogers/MetroHash
- * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/
- * 来自:https://github.com/postamar/java-metrohash/
+ * 官方实现:MetroHash
+ * 官方文档:metrohash
+ * 来自:java-metrohash
+ *
* @author Marius Posta
*/
public class MetroHash128 extends AbstractMetroHash implements Hash128 {
@@ -37,7 +38,7 @@ public class MetroHash128 extends AbstractMetroHash implements Has
/**
* 创建 {@code MetroHash128}对象
*
- * @param seed 种子
+ * @param seed 种子
* @return {@code MetroHash128}对象
*/
public static MetroHash128 of(final long seed) {
diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash64.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash64.java
index c207e9708b..364f62bb7f 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash64.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/hash/metro/MetroHash64.java
@@ -26,9 +26,10 @@ import java.nio.ByteOrder;
* 除了卓越的性能外,他们还以算法生成而著称。
*
*
- * 官方实现:https://github.com/jandrewrogers/MetroHash
- * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/
- * 来自:https://github.com/postamar/java-metrohash/
+ * 官方实现:MetroHash
+ * 官方文档:metrohash
+ * 来自:java-metrohash
+ *
* @author Marius Posta
*/
public class MetroHash64 extends AbstractMetroHash implements Hash64 {
@@ -36,7 +37,7 @@ public class MetroHash64 extends AbstractMetroHash implements Hash6
/**
* 创建 {@code MetroHash64}对象
*
- * @param seed 种子
+ * @param seed 种子
* @return {@code MetroHash64}对象
*/
public static MetroHash64 of(final long seed) {
@@ -82,9 +83,9 @@ public class MetroHash64 extends AbstractMetroHash implements Hash6
@Override
public MetroHash64 write(final ByteBuffer output, final ByteOrder byteOrder) {
- if(ByteOrder.LITTLE_ENDIAN == byteOrder){
+ if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
writeLittleEndian(hash, output);
- } else{
+ } else {
output.asLongBuffer().put(hash);
}
return this;
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/RadixUtilTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/RadixUtilTest.java
index 35e595aa39..669e2b1eb5 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/codec/RadixUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/RadixUtilTest.java
@@ -18,7 +18,7 @@ package cn.hutool.v7.core.codec;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
public class RadixUtilTest {
@Test
@@ -29,4 +29,151 @@ public class RadixUtilTest {
RadixUtil.decode(radixs, bad);
});
}
+
+ @Test
+ public void testEncodeInt() {
+ // Test binary conversion (base 2)
+ assertEquals("1010", RadixUtil.encode("01", 10));
+
+ // Test base 3 conversion
+ assertEquals("101", RadixUtil.encode("012", 10));
+
+ // Test base 16 conversion
+ assertEquals("A", RadixUtil.encode("0123456789ABCDEF", 10));
+
+ // Test with 34-radix
+ assertEquals("Y", RadixUtil.encode(RadixUtil.RADIXS_34, 32));
+
+ // Test with 59-radix
+ assertEquals("b", RadixUtil.encode(RadixUtil.RADIXS_59, 11));
+ }
+
+ @Test
+ public void testEncodeLong() {
+ // Test binary conversion (base 2)
+ assertEquals("1010", RadixUtil.encode("01", 10L));
+
+ // Test base 3 conversion
+ assertEquals("101", RadixUtil.encode("012", 10L));
+
+ // Test larger number
+ assertEquals("RR", RadixUtil.encode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 999L));
+
+ // Test with shuffle 34-radix
+ assertEquals("R", RadixUtil.encode(RadixUtil.RADIXS_SHUFFLE_34, 22));
+ }
+
+ @Test
+ public void testDecodeToInt() {
+ // Test binary decoding (base 2)
+ assertEquals(10, RadixUtil.decodeToInt("01", "1010"));
+
+ // Test base 3 decoding
+ assertEquals(10, RadixUtil.decodeToInt("012", "101"));
+
+ // Test base 16 decoding
+ assertEquals(10, RadixUtil.decodeToInt("0123456789ABCDEF", "A"));
+
+ // Test with 34-radix
+ assertEquals(30, RadixUtil.decodeToInt(RadixUtil.RADIXS_34, "W"));
+ }
+
+ @Test
+ public void testDecode() {
+ // Test binary decoding (base 2)
+ assertEquals(10L, RadixUtil.decode("01", "1010"));
+
+ // Test base 3 decoding
+ assertEquals(10L, RadixUtil.decode("012", "101"));
+
+ // Test base 16 decoding
+ assertEquals(10L, RadixUtil.decode("0123456789ABCDEF", "A"));
+
+ // Test with 59-radix
+ assertEquals(11L, RadixUtil.decode(RadixUtil.RADIXS_59, "b"));
+
+ // Test with shuffle 59-radix
+ assertEquals(1L, RadixUtil.decode(RadixUtil.RADIXS_SHUFFLE_59, "vh"));
+ }
+
+ @Test
+ public void testEncodeDecodeRoundTrip() {
+ // Test round trip for various bases
+ assertEquals(42, RadixUtil.decodeToInt("01", RadixUtil.encode("01", 42)));
+ assertEquals(123, RadixUtil.decodeToInt("0123456789", RadixUtil.encode("0123456789", 123)));
+ assertEquals(255, RadixUtil.decodeToInt("0123456789ABCDEF", RadixUtil.encode("0123456789ABCDEF", 255)));
+
+ // Test with predefined radixes
+ assertEquals(1000, RadixUtil.decodeToInt(RadixUtil.RADIXS_34, RadixUtil.encode(RadixUtil.RADIXS_34, 1000)));
+ assertEquals(2000, RadixUtil.decodeToInt(RadixUtil.RADIXS_59, RadixUtil.encode(RadixUtil.RADIXS_59, 2000)));
+ assertEquals(500, RadixUtil.decodeToInt(RadixUtil.RADIXS_SHUFFLE_34, RadixUtil.encode(RadixUtil.RADIXS_SHUFFLE_34, 500)));
+ assertEquals(750, RadixUtil.decodeToInt(RadixUtil.RADIXS_SHUFFLE_59, RadixUtil.encode(RadixUtil.RADIXS_SHUFFLE_59, 750)));
+ }
+
+ @Test
+ public void testEdgeCases() {
+ // Test zero
+ assertEquals("0", RadixUtil.encode("01", 0));
+ assertEquals(0, RadixUtil.decodeToInt("01", "0"));
+
+ // Test single digit numbers
+ assertEquals("1", RadixUtil.encode("01", 1));
+ assertEquals(1, RadixUtil.decodeToInt("01", "1"));
+
+ // Test with larger numbers
+ assertEquals("11111111", RadixUtil.encode("01", 255)); // 255 in binary
+ assertEquals(255, RadixUtil.decodeToInt("01", "11111111"));
+
+ // Test negative numbers (using the special handling in encode)
+ assertEquals(4294967254L, RadixUtil.decode("01", RadixUtil.encode("01", -42)));
+ }
+
+ @SuppressWarnings("ConstantValue")
+ @Test
+ public void testPredefinedRadixes() {
+ // Test 34-radix constants
+ assertNotNull(RadixUtil.RADIXS_34);
+ assertEquals(34, RadixUtil.RADIXS_34.length());
+ assertFalse(RadixUtil.RADIXS_34.contains("I"));
+ assertFalse(RadixUtil.RADIXS_34.contains("O"));
+
+ // Test 59-radix constants
+ assertNotNull(RadixUtil.RADIXS_59);
+ assertEquals(59, RadixUtil.RADIXS_59.length());
+ assertFalse(RadixUtil.RADIXS_59.contains("I"));
+ assertFalse(RadixUtil.RADIXS_59.contains("O"));
+ assertFalse(RadixUtil.RADIXS_59.contains("l"));
+
+ // Test shuffle radixes
+ assertNotNull(RadixUtil.RADIXS_SHUFFLE_34);
+ assertEquals(34, RadixUtil.RADIXS_SHUFFLE_34.length());
+
+ assertNotNull(RadixUtil.RADIXS_SHUFFLE_59);
+ assertEquals(59, RadixUtil.RADIXS_SHUFFLE_59.length());
+ }
+
+ @Test
+ public void testInvalidInputs() {
+ // Test invalid radix (too short)
+ assertThrows(RuntimeException.class, () -> RadixUtil.encode("0", 10)); // only 1 char
+
+ // Test decode with null radix
+ assertThrows(IllegalArgumentException.class, () -> RadixUtil.decode(null, "10"));
+
+ // Test decode with empty string
+ assertThrows(IllegalArgumentException.class, () -> RadixUtil.decode("01", ""));
+
+ // Test decode with invalid character (already tested in original method)
+ final String radixs = "0123456789ABC"; // base 13
+ final String bad = "1X3"; // 'X' 不在 radix 中
+ assertThrows(IllegalArgumentException.class, () -> RadixUtil.decode(radixs, bad));
+ }
+
+ @Test
+ public void testLongValueEncodeDecode() {
+ final long testValue = 1234567890L;
+ final String encoded = RadixUtil.encode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", testValue);
+ final long decoded = RadixUtil.decode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", encoded);
+ assertEquals(testValue, decoded);
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base32Test.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base32Test.java
similarity index 96%
rename from hutool-core/src/test/java/cn/hutool/v7/core/codec/Base32Test.java
rename to hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base32Test.java
index 8dfc261336..3a0716f0d7 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base32Test.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base32Test.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package cn.hutool.v7.core.codec;
+package cn.hutool.v7.core.codec.binary;
-import cn.hutool.v7.core.codec.binary.Base32;
import cn.hutool.v7.core.util.ByteUtil;
import cn.hutool.v7.core.util.RandomUtil;
import org.junit.jupiter.api.Assertions;
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base58Test.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base58Test.java
similarity index 95%
rename from hutool-core/src/test/java/cn/hutool/v7/core/codec/Base58Test.java
rename to hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base58Test.java
index 6654bf1e04..9e9698c8cc 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base58Test.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base58Test.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package cn.hutool.v7.core.codec;
+package cn.hutool.v7.core.codec.binary;
-import cn.hutool.v7.core.codec.binary.Base58;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base62Test.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base62Test.java
similarity index 96%
rename from hutool-core/src/test/java/cn/hutool/v7/core/codec/Base62Test.java
rename to hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base62Test.java
index e9d6d24634..015ca4dfe4 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base62Test.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base62Test.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package cn.hutool.v7.core.codec;
+package cn.hutool.v7.core.codec.binary;
-import cn.hutool.v7.core.codec.binary.Base62;
import cn.hutool.v7.core.util.RandomUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base64Test.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base64Test.java
similarity index 98%
rename from hutool-core/src/test/java/cn/hutool/v7/core/codec/Base64Test.java
rename to hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base64Test.java
index 12c58b2525..38f9481931 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/codec/Base64Test.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/Base64Test.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package cn.hutool.v7.core.codec;
+package cn.hutool.v7.core.codec.binary;
-import cn.hutool.v7.core.codec.binary.Base64;
import cn.hutool.v7.core.util.ByteUtil;
import cn.hutool.v7.core.util.CharsetUtil;
import cn.hutool.v7.core.util.RandomUtil;
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/HexUtilTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/HexUtilTest.java
new file mode 100644
index 0000000000..0dded93a48
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/binary/HexUtilTest.java
@@ -0,0 +1,202 @@
+package cn.hutool.v7.core.codec.binary;
+
+import org.junit.jupiter.api.Test;
+
+import java.awt.Color;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class HexUtilTest {
+
+ @Test
+ public void testEncodeColor() {
+ final Color red = new Color(255, 0, 0);
+ assertEquals("#ff0000", HexUtil.encodeColor(red));
+
+ final Color green = new Color(0, 255, 0);
+ assertEquals("#00ff00", HexUtil.encodeColor(green));
+
+ final Color blue = new Color(0, 0, 255);
+ assertEquals("#0000ff", HexUtil.encodeColor(blue));
+
+ final Color black = new Color(0, 0, 0);
+ assertEquals("#000000", HexUtil.encodeColor(black));
+
+ final Color white = new Color(255, 255, 255);
+ assertEquals("#ffffff", HexUtil.encodeColor(white));
+
+ // Test with single digit values (should be padded with 0)
+ final Color testColor = new Color(1, 16, 255);
+ assertEquals("#0110ff", HexUtil.encodeColor(testColor));
+ }
+
+ @Test
+ public void testEncodeColorWithPrefix() {
+ final Color red = new Color(255, 0, 0);
+ assertEquals("0xff0000", HexUtil.encodeColor(red, "0x"));
+ assertEquals("#ff0000", HexUtil.encodeColor(red, "#"));
+ assertEquals("ff0000", HexUtil.encodeColor(red, ""));
+ }
+
+ @Test
+ public void testDecodeColor() {
+ assertEquals(new Color(255, 0, 0), HexUtil.decodeColor("#ff0000"));
+ assertEquals(new Color(0, 255, 0), HexUtil.decodeColor("#00ff00"));
+ assertEquals(new Color(0, 0, 255), HexUtil.decodeColor("#0000ff"));
+ assertEquals(new Color(255, 0, 0), HexUtil.decodeColor("0xff0000"));
+ }
+
+ @Test
+ public void testIsHexNumber() {
+ assertTrue(HexUtil.isHexNumber("ff"));
+ assertTrue(HexUtil.isHexNumber("FF"));
+ assertTrue(HexUtil.isHexNumber("0xff"));
+ assertTrue(HexUtil.isHexNumber("0XFF"));
+ assertTrue(HexUtil.isHexNumber("#ff"));
+ assertTrue(HexUtil.isHexNumber("123abc"));
+ assertTrue(HexUtil.isHexNumber("0x123abc"));
+ assertTrue(HexUtil.isHexNumber("#123abc"));
+
+ assertFalse(HexUtil.isHexNumber(""));
+ assertFalse(HexUtil.isHexNumber(null));
+ assertFalse(HexUtil.isHexNumber("gg")); // g is not hex digit
+ assertFalse(HexUtil.isHexNumber("-ff"));
+ assertFalse(HexUtil.isHexNumber("ff-"));
+ assertFalse(HexUtil.isHexNumber("12 34")); // space not allowed
+ }
+
+ @Test
+ public void testToUnicodeHex() {
+ assertEquals("\\u4f60", HexUtil.toUnicodeHex('你'));
+ assertEquals("\\u0048", HexUtil.toUnicodeHex('H'));
+ assertEquals("\\u0065", HexUtil.toUnicodeHex('e'));
+ assertEquals("\\u006c", HexUtil.toUnicodeHex('l'));
+ assertEquals("\\u006f", HexUtil.toUnicodeHex('o'));
+
+ // Test with integer values
+ assertEquals("\\u0041", HexUtil.toUnicodeHex(65)); // 'A'
+ assertEquals("\\u0000", HexUtil.toUnicodeHex(0));
+ assertEquals("\\uffff", HexUtil.toUnicodeHex(65535)); // max char value
+ }
+
+ @Test
+ public void testToHexFromInt() {
+ assertEquals("ff", HexUtil.toHex(255));
+ assertEquals("0", HexUtil.toHex(0));
+ assertEquals("10", HexUtil.toHex(16));
+ assertEquals("64", HexUtil.toHex(100));
+ assertEquals("ffff", HexUtil.toHex(65535));
+ }
+
+ @Test
+ public void testHexToInt() {
+ assertEquals(255, HexUtil.hexToInt("ff"));
+ assertEquals(255, HexUtil.hexToInt("0xff"));
+ assertEquals(255, HexUtil.hexToInt("#ff"));
+ assertEquals(0, HexUtil.hexToInt("0"));
+ assertEquals(16, HexUtil.hexToInt("10"));
+ assertEquals(100, HexUtil.hexToInt("64"));
+ assertEquals(65535, HexUtil.hexToInt("ffff"));
+ assertEquals(65535, HexUtil.hexToInt("0xffff"));
+ }
+
+ @Test
+ public void testToHexFromLong() {
+ assertEquals("ff", HexUtil.toHex(255L));
+ assertEquals("0", HexUtil.toHex(0L));
+ assertEquals("10", HexUtil.toHex(16L));
+ assertEquals("ffffffffffffffff", HexUtil.toHex(-1L));
+ }
+
+ @Test
+ public void testHexToLong() {
+ assertEquals(255L, HexUtil.hexToLong("ff"));
+ assertEquals(255L, HexUtil.hexToLong("0xff"));
+ assertEquals(0L, HexUtil.hexToLong("0"));
+ assertEquals(16L, HexUtil.hexToLong("10"));
+ assertThrows(NumberFormatException.class, ()-> HexUtil.hexToLong("ffffffffffffffff"));
+ }
+
+ @Test
+ public void testToHexFromFloat() {
+ assertEquals("40490fdb", HexUtil.toHex((float) Math.PI));
+ assertEquals("0", HexUtil.toHex(0.0f));
+ assertEquals("3f800000", HexUtil.toHex(1.0f));
+ }
+
+ @Test
+ public void testHexToFloat() {
+ assertEquals(Math.PI, HexUtil.hexToFloat("40490fdb"), 0.0001f);
+ assertEquals(0.0f, HexUtil.hexToFloat("0"), 0.0001f);
+ assertEquals(1.0f, HexUtil.hexToFloat("3f800000"), 0.0001f);
+ }
+
+ @Test
+ public void testToHexFromDouble() {
+ assertEquals("400921fb54442d18", HexUtil.toHex(Math.PI));
+ assertEquals("0", HexUtil.toHex(0.0));
+ assertEquals("3ff0000000000000", HexUtil.toHex(1.0));
+ }
+
+ @Test
+ public void testHexToDouble() {
+ assertEquals(Math.PI, HexUtil.hexToDouble("400921fb54442d18"), 0.0001);
+ assertEquals(0.0, HexUtil.hexToDouble("0"), 0.0001);
+ assertEquals(1.0, HexUtil.hexToDouble("3ff0000000000000"), 0.0001);
+ }
+
+ @Test
+ public void testAppendHex() {
+ StringBuilder sb = new StringBuilder();
+ HexUtil.appendHex(sb, (byte) 255, true); // lowercase
+ assertEquals("ff", sb.toString());
+
+ sb = new StringBuilder();
+ HexUtil.appendHex(sb, (byte) 255, false); // uppercase
+ assertEquals("FF", sb.toString());
+
+ sb = new StringBuilder();
+ HexUtil.appendHex(sb, (byte) 0, true);
+ assertEquals("00", sb.toString());
+
+ sb = new StringBuilder();
+ HexUtil.appendHex(sb, (byte) 16, true);
+ assertEquals("10", sb.toString());
+ }
+
+ @Test
+ public void testToBigInteger() {
+ assertNull(HexUtil.toBigInteger(null));
+ assertEquals(new java.math.BigInteger("ff", 16), HexUtil.toBigInteger("ff"));
+ assertEquals(new java.math.BigInteger("ff", 16), HexUtil.toBigInteger("0xff"));
+ assertEquals(new java.math.BigInteger("ff", 16), HexUtil.toBigInteger("#ff"));
+ assertEquals(new java.math.BigInteger("0", 16), HexUtil.toBigInteger("0"));
+ assertEquals(new java.math.BigInteger("1234abcd", 16), HexUtil.toBigInteger("1234abcd"));
+ }
+
+ @Test
+ public void testFormat() {
+ assertEquals("", HexUtil.format(""));
+ assertEquals("a", HexUtil.format("a"));
+ assertEquals("ab", HexUtil.format("ab"));
+ assertEquals("ab cd", HexUtil.format("abcd"));
+ assertEquals("ab cd ef", HexUtil.format("abcdef"));
+ assertEquals("ab cd ef 12", HexUtil.format("abcdef12"));
+ }
+
+ @Test
+ public void testFormatWithPrefix() {
+ assertEquals("0xab", HexUtil.format("ab", "0x"));
+ assertEquals("0xab 0xcd", HexUtil.format("abcd", "0x"));
+ assertEquals("#ab", HexUtil.format("ab", "#"));
+ assertEquals("#ab #cd", HexUtil.format("abcd", "#"));
+ }
+
+ @Test
+ public void testFormatWithPrefixAndSeparator() {
+ assertEquals("0xab 0xcd", HexUtil.format("abcd", "0x", " "));
+ assertEquals("0xab:0xcd", HexUtil.format("abcd", "0x", ":"));
+ assertEquals("ab-cd", HexUtil.format("abcd", "", "-"));
+ assertEquals("ab cd ef 12", HexUtil.format("abcdef12", null, null));
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/codec/hash/ConsistentHashTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/codec/hash/ConsistentHashTest.java
new file mode 100644
index 0000000000..8189f45f64
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/codec/hash/ConsistentHashTest.java
@@ -0,0 +1,214 @@
+package cn.hutool.v7.core.codec.hash;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class ConsistentHashTest {
+
+ @Test
+ public void testConstructorWithDefaultHashFunction() {
+ final List nodes = Arrays.asList("node1", "node2", "node3");
+ final ConsistentHash consistentHash = new ConsistentHash<>(3, nodes);
+
+ assertNotNull(consistentHash);
+ // Cannot directly access numberOfReplicas and circle as they are private
+ // We'll test the functionality instead
+ final String node = consistentHash.get("testKey");
+ assertNotNull(node);
+ assertTrue(nodes.contains(node));
+ }
+
+ @Test
+ public void testConstructorWithCustomHashFunction() {
+ final Hash32