Compare commits

..

11 Commits

Author SHA1 Message Date
1509597032
Merge pull request 'dev' (#12) from dev into master
Reviewed-on: #12
2025-09-21 15:41:49 +08:00
ac92f62967
build(jdk8): 更新构建脚本中的 Kotlin 和 Dokka 插件版本- 在 jdk8/build.gradle.kts 中添加了 Kotlin JVM 插件和 Dokka 插件
- 更新 `build.gradle.kts` 中的 Dokka 版本从2.1.0-Beta 到2.0.0- 调整了 Gradle 任务依赖方式,使用字符串名称替代任务引用
- 升级项目版本号从 4.1.8 到 4.1.9
2025-09-21 15:39:14 +08:00
683aeb2c7f
```
feat(stream): 优化 SuperStream 的 toArray 方法实现- 调整 toArray 方法,支持传入 Class 参数以正确创建泛型数组
- 原无参 toArray 方法改为返回 Object[],避免类型转换异常
- 移除对 ForEach 工具类的依赖
- 提升流处理中数组转换的灵活性与安全性

```

```
feat(collection): 改进 toArray 工具方法支持泛型数组创建

- 新增基于 reified 泛型的 toArray 扩展方法,自动推断数组类型
- 添加带 Class 参数的 toArray 重载方法,用于明确指定元素类型
- 处理空列表时直接返回空数组,避免后续操作异常

```

```
build(gradle): 升级 dokka 插件版本并更新项目依赖- 将 org.jetbrains.dokka 插件升级至 2.1.0-Beta 版本
- 添加 jna5.17.0 依赖用于本地库调用支持
- 引入 mybatis-plus-core 3.0.1 编译依赖
- 更新项目版本号从 4.1.7 至 4.1.8

```
2025-09-21 14:37:22 +08:00
5eed682aa1
feat(utils): 添加 MyBatis-Plus 查询包装器支持
在 build.gradle.kts 中替换 JNA依赖为 mybatis-plus-core,并新增BaseMapperQuery 接口,提供通用的 QueryWrapper 实例创建方法,便于MyBatis-Plus 相关操作的统一封装与复用
2025-09-20 14:22:14 +08:00
578f0a3e89
fix(collection): 抑制类型转换警告并更新文件时间戳修复了 Collection.kt 文件中的类型转换警告问题,通过添加 @Suppress("UNCHECKED_CAST")
注解来抑制编译器警告。同时更新了文件的最后修改时
2025-09-20 14:05:41 +08:00
075dc2346a
feat(utils): 更新工具类并优化集合扩展函数
- 更新多个工具类的最后修改时间和用户信息
- 移除冗余的 main 函数测试代码
- 优化 ByteUtils 中流处理方法的引用- 为 Collection 扩展大量实用函数,包括转换、获取元素和创建集合实例等
- 引入 SuperStream 替代部分自定义流处理逻辑
- 调整 Spring Boot 自动配置包扫描路径- 修复资源读取时的空指针风险,使用 Kotlin 的 elvis 操作符简化代码
2025-09-20 14:01:36 +08:00
23548c0c3d
refactor(Base91): 更新Base91解码表并添加示例
更新了Base91解码表的初始化方式,并添加了一个示例方法来演示编码和解码功能。

feat(Base256): 添加Base256编解码器

新增了Base256类,实现了Base256编解码功能,并在BaseUtils中添加了相应的实例。

refactor(BaseCodec): 增加字符串编解码方法

在BaseCodec接口中增加了对字符串进行Base64编码和解码的方法。refactor(OsPath): 简化路径处理逻辑

移除了OsPath类中不必要的方法实现,简化了路径处理逻辑。

feat(UUID): 支持Base256短字符串

在UUID类中添加了对Base256短字符串的支持,包括编码和解码方法。
2025-09-18 14:43:01 +08:00
4b187f3774
添加 String.join 的文档
添加 List.join 的文档
添加 split 的文档
2025-09-18 09:28:06 +08:00
c90c1d590b
修改 List.join 为<T> 2025-09-18 09:24:43 +08:00
42a3302495
添加 String.join 方法 2025-09-18 09:23:19 +08:00
496c3e6248
更新List.join方法 2025-09-18 09:22:55 +08:00
32 changed files with 3042 additions and 503 deletions

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils * ModuleName mingli-utils
* CurrentFile build.gradle.kts * CurrentFile build.gradle.kts
* LastUpdate 2025-09-17 12:08:42 * LastUpdate 2025-09-21 15:36:59
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -77,6 +77,8 @@ dependencies {
compileOnly("com.google.code.gson:gson:2.13.1") compileOnly("com.google.code.gson:gson:2.13.1")
compileOnly("org.mybatis:mybatis:3.5.19") compileOnly("org.mybatis:mybatis:3.5.19")
compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58") compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58")
compileOnly("com.baomidou:mybatis-plus-core:3.0.1")
compileOnly("net.java.dev.jna:jna:5.17.0") compileOnly("net.java.dev.jna:jna:5.17.0")
} }
@ -99,7 +101,7 @@ tasks.withType<org.gradle.jvm.tasks.Jar> {
manifest { manifest {
attributes( attributes(
mapOf( mapOf(
"Main-Class" to "com.mingliqiye.utils.Main", "Main-Class" to "com.mingliqiye.utils.main.Main",
"Specification-Title" to ARTIFACTID, "Specification-Title" to ARTIFACTID,
"Specification-Version" to VERSIONS, "Specification-Version" to VERSIONS,
"Specification-Vendor" to "minglipro", "Specification-Vendor" to "minglipro",
@ -130,17 +132,16 @@ repositories {
} }
mavenCentral() mavenCentral()
} }
tasks.register<Jar>("javaDocJar") { tasks.register<Jar>("javaDocJar") {
group = "build" group = "build"
archiveClassifier.set("javadoc") archiveClassifier.set("javadoc")
dependsOn(tasks.dokkaJavadoc) dependsOn("dokkaJavadoc")
from(buildDir.resolve("dokka/javadoc")) from(buildDir.resolve("dokka/javadoc"))
} }
tasks.register<Jar>("kotlinDocJar") { tasks.register<Jar>("kotlinDocJar") {
group = "build" group = "build"
archiveClassifier.set("kotlindoc") archiveClassifier.set("kotlindoc")
dependsOn(tasks.dokkaHtml) dependsOn("dokkaHtml")
from(buildDir.resolve("dokka/html")) from(buildDir.resolve("dokka/html"))
} }
publishing { publishing {
@ -213,5 +214,3 @@ tasks.processResources {
) )
} }
} }

View File

@ -16,13 +16,13 @@
# ProjectName mingli-utils # ProjectName mingli-utils
# ModuleName mingli-utils # ModuleName mingli-utils
# CurrentFile gradle.properties # CurrentFile gradle.properties
# LastUpdate 2025-09-17 21:09:18 # LastUpdate 2025-09-21 15:38:52
# UpdateUser MingLiPro # UpdateUser MingLiPro
# #
JDKVERSIONS=1.8 JDKVERSIONS=1.8
GROUPSID=com.mingliqiye.utils GROUPSID=com.mingliqiye.utils
ARTIFACTID=mingli-utils ARTIFACTID=mingli-utils
VERSIONS=4.1.4 VERSIONS=4.1.9
signing.keyId=B22AA93B signing.keyId=B22AA93B
signing.password= signing.password=
signing.secretKeyRingFile=secret.gpg signing.secretKeyRingFile=secret.gpg

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.jdk8 * ModuleName mingli-utils.jdk8
* CurrentFile build.gradle.kts * CurrentFile build.gradle.kts
* LastUpdate 2025-09-17 11:07:31 * LastUpdate 2025-09-21 15:39:12
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -24,6 +24,8 @@ plugins {
id("java-library") id("java-library")
id("maven-publish") id("maven-publish")
signing signing
kotlin("jvm") version "2.2.20"
id("org.jetbrains.dokka") version "2.0.0"
} }
val GROUPSID = project.properties["GROUPSID"] as String val GROUPSID = project.properties["GROUPSID"] as String
val VERSIONS = project.properties["VERSIONS"] as String val VERSIONS = project.properties["VERSIONS"] as String

View File

@ -15,29 +15,20 @@
* *
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile ComponentBean.kt * CurrentFile StreamEmptyException.java
* LastUpdate 2025-09-15 22:32:50 * LastUpdate 2025-09-20 13:24:07
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.bean.annotation package com.mingliqiye.utils.stream;
import kotlin.annotation.AnnotationRetention.RUNTIME public class StreamEmptyException extends java.lang.RuntimeException {
import kotlin.annotation.AnnotationTarget.CLASS
import kotlin.annotation.AnnotationTarget.FIELD
/** public StreamEmptyException(String message) {
* 组件bean注解 super(message);
* @author MingLiPro }
*/
@Retention(RUNTIME)
@Target(CLASS)
annotation class ComponentBean(val value: String = "")
/** public StreamEmptyException(String message, Throwable cause) {
* 注入bean注解 super(message, cause);
* @author MingLiPro }
*/ }
@Retention(RUNTIME)
@Target(FIELD)
annotation class InjectBean(val value: String = "")

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile AesUtils.kt * CurrentFile AesUtils.kt
* LastUpdate 2025-09-17 10:40:03 * LastUpdate 2025-09-19 21:35:53
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -121,3 +121,4 @@ private fun createSecretKey(sKey: String): SecretKeySpec {
val digest = md.digest(key) val digest = md.digest(key)
return SecretKeySpec(digest, ALGORITHM) return SecretKeySpec(digest, ALGORITHM)
} }

View File

@ -0,0 +1,313 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base256.kt
* LastUpdate 2025-09-20 14:01:29
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.base
/**
* Base256 字符集 256
*
* 256个字符 要字符集的下面复制
*
* !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~§±×÷
*
*/
class Base256 : BaseCodec {
companion object {
val code = arrayOf(
'!',
'#',
'$',
'%',
'&',
'(',
')',
'*',
'+',
',',
'-',
'.',
'/',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
':',
';',
'<',
'=',
'>',
'?',
'@',
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'[',
']',
'^',
'_',
'`',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'{',
'|',
'}',
'~',
'§',
'±',
'×',
'÷',
'←',
'↑',
'→',
'↓',
'⇒',
'⇔',
'∀',
'∃',
'∅',
'∆',
'∇',
'∈',
'∉',
'∋',
'∌',
'∏',
'∑',
'',
'∓',
'',
'',
'∘',
'∙',
'√',
'∛',
'∜',
'∞',
'∟',
'∠',
'',
'∥',
'∧',
'',
'∩',
'',
'∫',
'∬',
'∭',
'∮',
'∯',
'∰',
'∱',
'∲',
'∳',
'∴',
'∵',
'',
'∷',
'≈',
'≠',
'≡',
'≤',
'≥',
'≦',
'≧',
'≪',
'≫',
'≺',
'≻',
'⊂',
'⊃',
'⊆',
'⊇',
'⊈',
'⊉',
'⊊',
'⊋',
'⊕',
'⊖',
'⊗',
'⊘',
'⊙',
'⊚',
'⊛',
'⊜',
'⊝',
'⊞',
'⊟',
'⊠',
'⊡',
'⊢',
'⊣',
'',
'⊥',
'⊦',
'⊧',
'⊨',
'⊩',
'⊪',
'⊫',
'⊬',
'⊭',
'⊮',
'⊯',
'⋀',
'',
'⋂',
'',
'⋄',
'⋅',
'⋆',
'⋇',
'⋈',
'⋉',
'⋊',
'⋋',
'⋌',
'⋍',
'⋎',
'⋏',
'⋐',
'⋑',
'⋒',
'⋓',
'⋔',
'⋕',
'⋖',
'⋗',
'⋘',
'⋙',
'⋚',
'⋛',
'⋜',
'⋝',
'⋞',
'⋟',
'⋠',
'⋡',
'⋢',
'⋣',
'⋤',
'⋥',
'⋦',
'⋧',
'⋨',
'⋩',
'▁',
'▂',
'▃',
'▄',
'▅',
'▆',
'▇',
'█',
'▉',
'▊',
'▋',
'▌',
'▍',
'▎',
'▏',
'▐',
'░',
'▒',
'▓',
'▔',
'▕',
'▖',
'▗',
'▘',
'▙'
)
val codeMap = code.mapIndexed { index, c -> c to index }.toMap()
}
override fun encode(bytes: ByteArray): String {
val result = CharArray(bytes.size)
for (i in bytes.indices) {
val unsignedByte = bytes[i].toInt() and 0xFF
result[i] = code[unsignedByte]
}
return String(result)
}
override fun decode(string: String): ByteArray {
val result = ByteArray(string.length)
for (i in string.indices) {
result[i] = codeMap[string[i]]!!.toByte()
}
return result
}
}

View File

@ -16,14 +16,12 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Base91.kt * CurrentFile Base91.kt
* LastUpdate 2025-09-17 10:57:36 * LastUpdate 2025-09-19 20:08:46
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.base package com.mingliqiye.utils.base
import java.util.*
/** /**
* Base91 编解码工具类用于将字节数组编码为 Base91 字符串或将 Base91 字符串解码为原始字节数组 * Base91 编解码工具类用于将字节数组编码为 Base91 字符串或将 Base91 字符串解码为原始字节数组
* *
@ -49,16 +47,264 @@ class Base91 : BaseCodec {
* Base91 解码表大小为 256用于快速查找字符对应的数值 * Base91 解码表大小为 256用于快速查找字符对应的数值
* 初始化时将所有元素设为 -1表示无效字符然后根据 ENCODING_TABLE 填充有效字符的索引 * 初始化时将所有元素设为 -1表示无效字符然后根据 ENCODING_TABLE 填充有效字符的索引
*/ */
val DECODING_TABLE: IntArray = IntArray(256) val DECODING_TABLE: Array<Int> = arrayOf(
-1,
init { -1,
// 初始化解码表,默认值为 -1 表示该字符不在编码表中 -1,
Arrays.fill(DECODING_TABLE, -1); -1,
// 构建解码映射表 -1,
for (i in 0..<ENCODING_TABLE.size) { -1,
DECODING_TABLE[ENCODING_TABLE[i].code] = i; -1,
} -1,
} -1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
62,
90,
63,
64,
65,
66,
-1,
67,
68,
69,
70,
71,
-1,
72,
73,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
74,
75,
76,
77,
78,
79,
80,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
81,
-1,
82,
83,
84,
85,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
86,
87,
88,
89,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
)
} }
/** /**

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile BaseCodec.kt * CurrentFile BaseCodec.kt
* LastUpdate 2025-09-17 10:35:23 * LastUpdate 2025-09-18 14:07:35
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -150,4 +150,24 @@ interface BaseCodec {
false false
} }
} }
/**
* 将字符串编码为Base64字符串
*
* @param string 需要编码的字符串
* @return 编码后的Base64字符串
*/
fun encode(string: String): String {
return encode(string.toByteArray())
}
/**
* 将Base64字符串解码为字符串
*
* @param string 需要解码的Base64字符串
* @return 解码后的字符串
*/
fun decodetoString(string: String): String {
return decode(string).toString(Charsets.UTF_8)
}
} }

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile BaseUtils.kt * CurrentFile BaseUtils.kt
* LastUpdate 2025-09-17 10:54:46 * LastUpdate 2025-09-19 20:18:09
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -51,4 +51,13 @@ val BASE16: BaseCodec by lazy {
Base16() Base16()
} }
/**
* Base256编解码器实例
* 使用懒加载方式初始化Base256编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE256: BaseCodec by lazy {
Base256()
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile BCrypt.kt * CurrentFile BCrypt.kt
* LastUpdate 2025-09-17 16:20:30 * LastUpdate 2025-09-19 20:17:41
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -57,4 +57,3 @@ fun gensalt(long: Int): String {
fun gensalt(long: Int, secureRandom: SecureRandom): String { fun gensalt(long: Int, secureRandom: SecureRandom): String {
return JBCrypt.gensalt(long, secureRandom) return JBCrypt.gensalt(long, secureRandom)
} }

View File

@ -1,241 +0,0 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Factory.kt
* LastUpdate 2025-09-15 22:32:50
* UpdateUser MingLiPro
*/
@file:JvmName("Factory")
package com.mingliqiye.utils.bean
import com.mingliqiye.utils.bean.annotation.ComponentBean
import com.mingliqiye.utils.bean.annotation.InjectBean
import java.io.File
import java.net.URL
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass
/**
* 存储所有已注册的Bean实例键为Bean名称值为Bean实例
*/
private val BEANS: ConcurrentHashMap<String, Any> = ConcurrentHashMap()
/**
* 存储按类型查找的Bean实例键为Bean的Class对象值为Bean实例
*/
private val TYPE_BEANS: ConcurrentHashMap<KClass<*>, Any> = ConcurrentHashMap()
/**
* 自动扫描指定类所在包下的所有类并注册为Bean
*
* @param c 指定的类用于获取其所在的包
* @throws IllegalArgumentException 如果传入的类为null或位于默认包中
*/
fun autoScan(c: Class<*>?) {
if (c == null) {
throw IllegalArgumentException("Class cannot be null")
}
val pkg = c.`package`
if (pkg == null) {
throw IllegalArgumentException("Class is in the default package")
}
scan(pkg.name)
}
/**
* 扫描指定包路径下的所有类文件并注册其中带有@ComponentBean注解的类为Bean
*
* @param basePackage 要扫描的基础包名
* @throws RuntimeException 如果在扫描过程中发生异常
*/
fun scan(basePackage: String) {
try {
val path = basePackage.replace('.', '/')
val classLoader = Thread.currentThread().contextClassLoader
val resources: Enumeration<URL> = classLoader.getResources(path)
while (resources.hasMoreElements()) {
val resource = resources.nextElement()
val file = File(resource.toURI())
scanDirectory(file, basePackage)
}
injectDependencies()
} catch (e: Exception) {
throw RuntimeException(e)
}
}
/**
* 递归扫描目录中的所有类文件并注册符合条件的类为Bean
*
* @param directory 当前要扫描的目录
* @param packageName 当前目录对应的包名
* @throws Exception 如果在扫描或类加载过程中发生异常
*/
private fun scanDirectory(directory: File, packageName: String) {
val files = directory.listFiles() ?: return
for (file in files) {
if (file.isDirectory) {
scanDirectory(file, "$packageName.${file.name}")
} else if (file.name.endsWith(".class")) {
val className = packageName + '.' + file.name.replace(".class", "")
registerComponent(Class.forName(className))
}
}
}
/**
* 注册一个带有@ComponentBean注解的类为Bean实例
*
* @param clazz 要注册的类
* @throws Exception 如果在实例化类或处理注解时发生异常
*/
private fun registerComponent(clazz: Class<*>) {
if (clazz.isAnnotationPresent(ComponentBean::class.java)) {
val component = clazz.getAnnotation(ComponentBean::class.java)
val name = component.value.ifEmpty { clazz.name }
val instance = clazz.getDeclaredConstructor().newInstance()
BEANS[name] = instance
val kClass = clazz.kotlin
TYPE_BEANS[kClass] = instance
for (interfaceClass in clazz.interfaces) {
TYPE_BEANS.putIfAbsent(interfaceClass.kotlin, instance)
}
}
}
/**
* 对所有已注册的Bean进行依赖注入处理
*
* @throws Exception 如果在注入过程中发生异常
*/
private fun injectDependencies() {
for (bean in BEANS.values) {
for (field in bean.javaClass.declaredFields) {
if (field.isAnnotationPresent(InjectBean::class.java)) {
val inject = field.getAnnotation(InjectBean::class.java)
val dependency = findDependency(field.type, inject.value)
if (dependency == null) {
throw IllegalStateException(
"No suitable dependency found for field " + field.name + " in class " + bean.javaClass.name
)
}
field.isAccessible = true
field.set(bean, dependency)
}
}
}
}
/**
* 根据类型和名称查找对应的依赖实例
*
* @param type 依赖的类型
* @param name 依赖的名称可为空
* @return 找到的依赖实例未找到则返回null
*/
private fun findDependency(type: Class<*>, name: String): Any? {
if (name.isNotEmpty()) {
return BEANS[name]
}
val dependency = TYPE_BEANS[type.kotlin]
if (dependency != null) {
return dependency
}
for (interfaceType in TYPE_BEANS.keys) {
if (type.isAssignableFrom(interfaceType.java)) {
return TYPE_BEANS[interfaceType]
}
}
return null
}
/**
* 将一个对象添加到Bean容器中使用其类名作为键
*
* @param obj 要添加的对象
* @throws RuntimeException 如果在注入依赖时发生异常
*/
fun add(obj: Any) {
val clazz = obj.javaClass
val name = clazz.name
BEANS[name] = obj
TYPE_BEANS[clazz.kotlin] = obj
try {
injectDependencies()
} catch (e: Exception) {
throw RuntimeException(e)
}
}
/**
* 将一个对象以指定名称添加到Bean容器中
*
* @param name Bean的名称
* @param obj 要添加的对象
* @throws RuntimeException 如果在注入依赖时发生异常
*/
fun add(name: String, obj: Any) {
BEANS[name] = obj
TYPE_BEANS[obj.javaClass.kotlin] = obj
try {
injectDependencies()
} catch (e: Exception) {
throw RuntimeException(e)
}
}
/**
* 根据类型获取对应的Bean实例
*
* @param objclass Bean的类型
* @param T Bean的泛型类型
* @return 对应类型的Bean实例未找到则返回null
*/
@Suppress("UNCHECKED_CAST")
fun <T : Any> get(objclass: KClass<T>): T? {
return TYPE_BEANS[objclass] as? T
}
/**
* 根据名称和类型获取对应的Bean实例
*
* @param name Bean的名称
* @param objclass Bean的类型
* @param T Bean的泛型类型
* @return 对应名称和类型的Bean实例未找到则返回null
*/
@Suppress("UNCHECKED_CAST")
fun <T : Any> get(name: String, objclass: KClass<T>): T? {
return BEANS[name] as? T
}
/**
* 根据名称获取对应的Bean实例
*
* @param name Bean的名称
* @return 对应名称的Bean实例未找到则返回null
*/
fun get(name: String): Any? {
return BEANS[name]
}

View File

@ -16,13 +16,15 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile ByteUtils.kt * CurrentFile ByteUtils.kt
* LastUpdate 2025-09-16 16:55:36 * LastUpdate 2025-09-20 11:49:05
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("ByteUtils") @file:JvmName("ByteUtils")
package com.mingliqiye.utils.bytes package com.mingliqiye.utils.bytes
import com.mingliqiye.utils.stream.SuperStream
const val ESC_ASC: Byte = 0x10 const val ESC_ASC: Byte = 0x10
const val ESC_DESC: Byte = 0x1B const val ESC_DESC: Byte = 0x1B
const val ESC_NONE: Byte = 0x00 const val ESC_NONE: Byte = 0x00
@ -40,7 +42,7 @@ const val ESC_RESERVED: Byte = 0x06
*/ */
fun ByteArray.getByteArrayString(): MutableList<String> { fun ByteArray.getByteArrayString(): MutableList<String> {
return this.toList().stream().map { a -> String.format("0X%02X", a!!.toInt() and 0xFF) } return this.toList().stream().map { a -> String.format("0X%02X", a!!.toInt() and 0xFF) }
.collect(com.mingliqiye.utils.stream.toList()) as MutableList<String> .collect(SuperStream.toList()) as MutableList<String>
} }

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile CloneUtils.kt * CurrentFile CloneUtils.kt
* LastUpdate 2025-09-15 09:30:37 * LastUpdate 2025-09-20 14:01:29
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("CloneUtils") @file:JvmName("CloneUtils")
@ -38,8 +38,7 @@ inline fun <reified T> T.deepJsonClone(jsonApi: JsonApi): T {
} catch (e: Exception) { } catch (e: Exception) {
throw JsonException( throw JsonException(
"Failed to deep clone object using JSON", "Failed to deep clone object using JSON", e
e
) )
} }
} }

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Collection.kt * CurrentFile Collection.kt
* LastUpdate 2025-09-15 17:26:00 * LastUpdate 2025-09-21 14:36:57
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -24,22 +24,48 @@
package com.mingliqiye.utils.collection package com.mingliqiye.utils.collection
import com.mingliqiye.utils.stream.SuperStream
import java.util.* import java.util.*
import java.util.stream.Collectors import java.util.stream.Collectors
/**
* 将当前集合转换为数组
*
* @param T 集合元素类型
* @return 转换后的数组
*/
inline fun <reified T> Collection<T>.toArray(): Array<T> { inline fun <reified T> Collection<T>.toArray(): Array<T> {
return arrayOf(*this.toTypedArray()) return arrayOf(*this.toTypedArray())
} }
/**
* 将当前集合转换为 Map其中键为集合元素本身值由给定函数生成
*
* @param T 集合元素类型
* @param V 映射值的类型
* @param v 用于生成映射值的函数
* @return 转换后的 Map
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified T, V> Collection<T>.toMap(noinline v: (T) -> V): Map<T, V> { inline fun <reified T, V> Collection<T>.toMap(noinline v: (T) -> V): Map<T, V> {
return this.stream().collect( return this.stream().collect(
com.mingliqiye.utils.stream.toMapValueThis( SuperStream.toMap(
v v
) )
) ) as Map<T, V>
} }
/**
* 将当前集合转换为 Map其中键和值分别由给定函数生成
*
* @param T 集合元素类型
* @param V 映射值的类型
* @param K 映射键的类型
* @param k 用于生成映射键的函数
* @param v 用于生成映射值的函数
* @return 转换后的 Map
*/
inline fun <reified T, V, K> Collection<T>.toMap(noinline k: (T) -> K, noinline v: (T) -> V): Map<K, V> { inline fun <reified T, V, K> Collection<T>.toMap(noinline k: (T) -> K, noinline v: (T) -> V): Map<K, V> {
return this.stream().collect( return this.stream().collect(
Collectors.toMap( Collectors.toMap(
@ -48,11 +74,24 @@ inline fun <reified T, V, K> Collection<T>.toMap(noinline k: (T) -> K, noinline
) )
} }
/**
* 将数组转换为 Set
*
* @param T 数组元素类型
* @param array 输入数组
* @return 转换后的 Set
*/
fun <T> toSet(array: Array<T>): Set<T> { fun <T> toSet(array: Array<T>): Set<T> {
return array.toSet() return array.toSet()
} }
/**
* 获取集合中的第一个元素如果集合为空则返回 null
*
* @param T 集合元素类型
* @return 第一个元素或 null
*/
inline fun <reified T> Collection<T>.getFirst(): T? { inline fun <reified T> Collection<T>.getFirst(): T? {
if (this.isEmpty()) { if (this.isEmpty()) {
return null return null
@ -63,6 +102,12 @@ inline fun <reified T> Collection<T>.getFirst(): T? {
return this.iterator().next() return this.iterator().next()
} }
/**
* 获取数组中的第一个元素如果数组为空则返回 null
*
* @param T 数组元素类型
* @return 第一个元素或 null
*/
inline fun <reified T> Array<T>.getFirst(): T? { inline fun <reified T> Array<T>.getFirst(): T? {
if (this.isEmpty()) { if (this.isEmpty()) {
return null return null
@ -70,6 +115,12 @@ inline fun <reified T> Array<T>.getFirst(): T? {
return this.first() return this.first()
} }
/**
* 获取集合中的最后一个元素如果集合为空则返回 null
*
* @param T 集合元素类型
* @return 最后一个元素或 null
*/
inline fun <reified T> Collection<T>.getLast(): T? { inline fun <reified T> Collection<T>.getLast(): T? {
if (this.isEmpty()) { if (this.isEmpty()) {
return null return null
@ -84,6 +135,12 @@ inline fun <reified T> Collection<T>.getLast(): T? {
return lastElement return lastElement
} }
/**
* 获取数组中的最后一个元素如果数组为空则返回 null
*
* @param T 数组元素类型
* @return 最后一个元素或 null
*/
inline fun <reified T> Array<T>.getLast(): T? { inline fun <reified T> Array<T>.getLast(): T? {
if (this.isEmpty()) { if (this.isEmpty()) {
return null return null
@ -92,6 +149,14 @@ inline fun <reified T> Array<T>.getLast(): T? {
} }
/**
* 根据索引获取集合中的元素若索引越界则返回默认值
*
* @param T 集合元素类型
* @param index 索引位置
* @param defaultValue 默认返回值
* @return 指定索引处的元素或默认值
*/
inline fun <reified T> Collection<T>.getOrDefault( inline fun <reified T> Collection<T>.getOrDefault(
index: Int, defaultValue: T index: Int, defaultValue: T
): T { ): T {
@ -111,54 +176,135 @@ inline fun <reified T> Collection<T>.getOrDefault(
return defaultValue return defaultValue
} }
/**
* 创建一个新的 ArrayList 实例
*
* @param T 元素类型
* @return 新创建的 ArrayList
*/
fun <T> newArrayList(): ArrayList<T> { fun <T> newArrayList(): ArrayList<T> {
return ArrayList() return ArrayList()
} }
/**
* 创建一个指定初始容量的新 ArrayList 实例
*
* @param T 元素类型
* @param size 初始容量大小
* @return 新创建的 ArrayList
*/
fun <T> newArrayList(size: Int): ArrayList<T> { fun <T> newArrayList(size: Int): ArrayList<T> {
return ArrayList() return ArrayList()
} }
/**
* 使用可变参数创建一个新的 ArrayList 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 ArrayList
*/
fun <T> newArrayList(vararg elements: T): ArrayList<T> { fun <T> newArrayList(vararg elements: T): ArrayList<T> {
return newArrayList(elements.asList()) return newArrayList(elements.asList())
} }
/**
* 将当前集合转换为新的 ArrayList 实例
*
* @param T 元素类型
* @return 新创建的 ArrayList
*/
fun <T> Collection<T>.newArrayLists(): ArrayList<T> { fun <T> Collection<T>.newArrayLists(): ArrayList<T> {
return newArrayList(this) return newArrayList(this)
} }
/**
* 将数组转换为新的 ArrayList 实例
*
* @param T 元素类型
* @param elements 输入数组
* @return 新创建的 ArrayList
*/
fun <T> newArrayLists(elements: Array<T>): ArrayList<T> { fun <T> newArrayLists(elements: Array<T>): ArrayList<T> {
return newArrayList(elements.asList()) return newArrayList(elements.asList())
} }
/**
* 将集合转换为新的 ArrayList 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 ArrayList
*/
fun <T> newArrayList(elements: Collection<T>): ArrayList<T> { fun <T> newArrayList(elements: Collection<T>): ArrayList<T> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* Iterable 转换为新的 ArrayList 实例
*
* @param T 元素类型
* @param elements 输入 Iterable
* @return 新创建的 ArrayList
*/
fun <T> newArrayList(elements: Iterable<T>): ArrayList<T> { fun <T> newArrayList(elements: Iterable<T>): ArrayList<T> {
return newArrayList(elements.toList()) return newArrayList(elements.toList())
} }
/**
* Sequence 转换为新的 ArrayList 实例
*
* @param T 元素类型
* @param elements 输入 Sequence
* @return 新创建的 ArrayList
*/
fun <T> newArrayList(elements: Sequence<T>): ArrayList<T> { fun <T> newArrayList(elements: Sequence<T>): ArrayList<T> {
return newArrayList(elements.toList()) return newArrayList(elements.toList())
} }
/**
* 创建一个新的 LinkedList 实例
*
* @param T 元素类型
* @return 新创建的 LinkedList
*/
fun <T> newLinkedList(): LinkedList<T> { fun <T> newLinkedList(): LinkedList<T> {
return LinkedList() return LinkedList()
} }
/**
* 使用可变参数创建一个新的 LinkedList 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 LinkedList
*/
fun <T> newLinkedList(vararg elements: T): LinkedList<T> { fun <T> newLinkedList(vararg elements: T): LinkedList<T> {
val list = newLinkedList<T>() val list = newLinkedList<T>()
list.addAll(elements.asList()) list.addAll(elements.asList())
return list return list
} }
/**
* 将集合转换为新的 LinkedList 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 LinkedList
*/
fun <T> newLinkedList(elements: Collection<T>): LinkedList<T> { fun <T> newLinkedList(elements: Collection<T>): LinkedList<T> {
val list = newLinkedList<T>() val list = newLinkedList<T>()
list.addAll(elements) list.addAll(elements)
return list return list
} }
/**
* Iterable 转换为新的 LinkedList 实例
*
* @param T 元素类型
* @param elements 输入 Iterable
* @return 新创建的 LinkedList
*/
fun <T> newLinkedList(elements: Iterable<T>): LinkedList<T> { fun <T> newLinkedList(elements: Iterable<T>): LinkedList<T> {
val list = newLinkedList<T>() val list = newLinkedList<T>()
for (element in elements) { for (element in elements) {
@ -167,26 +313,60 @@ fun <T> newLinkedList(elements: Iterable<T>): LinkedList<T> {
return list return list
} }
/**
* Sequence 转换为新的 LinkedList 实例
*
* @param T 元素类型
* @param elements 输入 Sequence
* @return 新创建的 LinkedList
*/
fun <T> newLinkedList(elements: Sequence<T>): LinkedList<T> { fun <T> newLinkedList(elements: Sequence<T>): LinkedList<T> {
return newLinkedList(elements.toList()) return newLinkedList(elements.toList())
} }
/**
* 创建一个新的 Vector 实例
*
* @param T 元素类型
* @return 新创建的 Vector
*/
fun <T> newVector(): Vector<T> { fun <T> newVector(): Vector<T> {
return Vector() return Vector()
} }
/**
* 使用可变参数创建一个新的 Vector 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 Vector
*/
fun <T> newVector(vararg elements: T): Vector<T> { fun <T> newVector(vararg elements: T): Vector<T> {
val vector = newVector<T>() val vector = newVector<T>()
vector.addAll(elements.asList()) vector.addAll(elements.asList())
return vector return vector
} }
/**
* 将集合转换为新的 Vector 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 Vector
*/
fun <T> newVector(elements: Collection<T>): Vector<T> { fun <T> newVector(elements: Collection<T>): Vector<T> {
val vector = newVector<T>() val vector = newVector<T>()
vector.addAll(elements) vector.addAll(elements)
return vector return vector
} }
/**
* Iterable 转换为新的 Vector 实例
*
* @param T 元素类型
* @param elements 输入 Iterable
* @return 新创建的 Vector
*/
fun <T> newVector(elements: Iterable<T>): Vector<T> { fun <T> newVector(elements: Iterable<T>): Vector<T> {
val vector = newVector<T>() val vector = newVector<T>()
for (element in elements) { for (element in elements) {
@ -195,31 +375,72 @@ fun <T> newVector(elements: Iterable<T>): Vector<T> {
return vector return vector
} }
/**
* Sequence 转换为新的 Vector 实例
*
* @param T 元素类型
* @param elements 输入 Sequence
* @return 新创建的 Vector
*/
fun <T> newVector(elements: Sequence<T>): Vector<T> { fun <T> newVector(elements: Sequence<T>): Vector<T> {
return newVector(elements.toList()) return newVector(elements.toList())
} }
/**
* 创建一个新的 HashSet 实例
*
* @param T 元素类型
* @return 新创建的 HashSet
*/
fun <T> newHashSet(): HashSet<T> { fun <T> newHashSet(): HashSet<T> {
return HashSet() return HashSet()
} }
/**
* 创建一个指定初始容量的新 HashSet 实例
*
* @param T 元素类型
* @param size 初始容量大小
* @return 新创建的 HashSet
*/
fun <T> newHashSet(size: Int): HashSet<T> { fun <T> newHashSet(size: Int): HashSet<T> {
return HashSet(size) return HashSet(size)
} }
/**
* 使用可变参数创建一个新的 HashSet 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 HashSet
*/
fun <T> newHashSet(vararg elements: T): HashSet<T> { fun <T> newHashSet(vararg elements: T): HashSet<T> {
val set = newHashSet<T>() val set = newHashSet<T>()
set.addAll(elements.asList()) set.addAll(elements.asList())
return set return set
} }
/**
* 将集合转换为新的 HashSet 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 HashSet
*/
fun <T> newHashSet(elements: Collection<T>): HashSet<T> { fun <T> newHashSet(elements: Collection<T>): HashSet<T> {
val set = newHashSet<T>() val set = newHashSet<T>()
set.addAll(elements) set.addAll(elements)
return set return set
} }
/**
* Iterable 转换为新的 HashSet 实例
*
* @param T 元素类型
* @param elements 输入 Iterable
* @return 新创建的 HashSet
*/
fun <T> newHashSet(elements: Iterable<T>): HashSet<T> { fun <T> newHashSet(elements: Iterable<T>): HashSet<T> {
val set = newHashSet<T>() val set = newHashSet<T>()
for (element in elements) { for (element in elements) {
@ -228,30 +449,71 @@ fun <T> newHashSet(elements: Iterable<T>): HashSet<T> {
return set return set
} }
/**
* Sequence 转换为新的 HashSet 实例
*
* @param T 元素类型
* @param elements 输入 Sequence
* @return 新创建的 HashSet
*/
fun <T> newHashSet(elements: Sequence<T>): HashSet<T> { fun <T> newHashSet(elements: Sequence<T>): HashSet<T> {
return newHashSet(elements.toSet()) return newHashSet(elements.toSet())
} }
/**
* 创建一个新的 LinkedHashSet 实例
*
* @param T 元素类型
* @return 新创建的 LinkedHashSet
*/
fun <T> newLinkedHashSet(): LinkedHashSet<T> { fun <T> newLinkedHashSet(): LinkedHashSet<T> {
return LinkedHashSet() return LinkedHashSet()
} }
/**
* 创建一个指定初始容量的新 LinkedHashSet 实例
*
* @param T 元素类型
* @param size 初始容量大小
* @return 新创建的 LinkedHashSet
*/
fun <T> newLinkedHashSet(size: Int): LinkedHashSet<T> { fun <T> newLinkedHashSet(size: Int): LinkedHashSet<T> {
return LinkedHashSet(size) return LinkedHashSet(size)
} }
/**
* 使用可变参数创建一个新的 LinkedHashSet 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 LinkedHashSet
*/
fun <T> newLinkedHashSet(vararg elements: T): LinkedHashSet<T> { fun <T> newLinkedHashSet(vararg elements: T): LinkedHashSet<T> {
val set = newLinkedHashSet<T>() val set = newLinkedHashSet<T>()
set.addAll(elements.asList()) set.addAll(elements.asList())
return set return set
} }
/**
* 将集合转换为新的 LinkedHashSet 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 LinkedHashSet
*/
fun <T> newLinkedHashSet(elements: Collection<T>): LinkedHashSet<T> { fun <T> newLinkedHashSet(elements: Collection<T>): LinkedHashSet<T> {
val set = newLinkedHashSet<T>() val set = newLinkedHashSet<T>()
set.addAll(elements) set.addAll(elements)
return set return set
} }
/**
* Iterable 转换为新的 LinkedHashSet 实例
*
* @param T 元素类型
* @param elements 输入 Iterable
* @return 新创建的 LinkedHashSet
*/
fun <T> newLinkedHashSet(elements: Iterable<T>): LinkedHashSet<T> { fun <T> newLinkedHashSet(elements: Iterable<T>): LinkedHashSet<T> {
val set = newLinkedHashSet<T>() val set = newLinkedHashSet<T>()
for (element in elements) { for (element in elements) {
@ -260,26 +522,60 @@ fun <T> newLinkedHashSet(elements: Iterable<T>): LinkedHashSet<T> {
return set return set
} }
/**
* Sequence 转换为新的 LinkedHashSet 实例
*
* @param T 元素类型
* @param elements 输入 Sequence
* @return 新创建的 LinkedHashSet
*/
fun <T> newLinkedHashSet(elements: Sequence<T>): LinkedHashSet<T> { fun <T> newLinkedHashSet(elements: Sequence<T>): LinkedHashSet<T> {
return newLinkedHashSet(elements.toSet()) return newLinkedHashSet(elements.toSet())
} }
/**
* 创建一个新的 TreeSet 实例
*
* @param T 元素类型必须实现 Comparable 接口
* @return 新创建的 TreeSet
*/
fun <T : Comparable<T>> newTreeSet(): TreeSet<T> { fun <T : Comparable<T>> newTreeSet(): TreeSet<T> {
return TreeSet() return TreeSet()
} }
/**
* 使用可变参数创建一个新的 TreeSet 实例
*
* @param T 元素类型必须实现 Comparable 接口
* @param elements 可变参数列表
* @return 新创建的 TreeSet
*/
fun <T : Comparable<T>> newTreeSet(vararg elements: T): TreeSet<T> { fun <T : Comparable<T>> newTreeSet(vararg elements: T): TreeSet<T> {
val set = newTreeSet<T>() val set = newTreeSet<T>()
set.addAll(elements.asList()) set.addAll(elements.asList())
return set return set
} }
/**
* 将集合转换为新的 TreeSet 实例
*
* @param T 元素类型必须实现 Comparable 接口
* @param elements 输入集合
* @return 新创建的 TreeSet
*/
fun <T : Comparable<T>> newTreeSet(elements: Collection<T>): TreeSet<T> { fun <T : Comparable<T>> newTreeSet(elements: Collection<T>): TreeSet<T> {
val set = newTreeSet<T>() val set = newTreeSet<T>()
set.addAll(elements) set.addAll(elements)
return set return set
} }
/**
* Iterable 转换为新的 TreeSet 实例
*
* @param T 元素类型必须实现 Comparable 接口
* @param elements 输入 Iterable
* @return 新创建的 TreeSet
*/
fun <T : Comparable<T>> newTreeSet(elements: Iterable<T>): TreeSet<T> { fun <T : Comparable<T>> newTreeSet(elements: Iterable<T>): TreeSet<T> {
val set = newTreeSet<T>() val set = newTreeSet<T>()
for (element in elements) { for (element in elements) {
@ -288,65 +584,160 @@ fun <T : Comparable<T>> newTreeSet(elements: Iterable<T>): TreeSet<T> {
return set return set
} }
/**
* Sequence 转换为新的 TreeSet 实例
*
* @param T 元素类型必须实现 Comparable 接口
* @param elements 输入 Sequence
* @return 新创建的 TreeSet
*/
fun <T : Comparable<T>> newTreeSet(elements: Sequence<T>): TreeSet<T> { fun <T : Comparable<T>> newTreeSet(elements: Sequence<T>): TreeSet<T> {
return newTreeSet(elements.toSet()) return newTreeSet(elements.toSet())
} }
/**
* 将字节数组转换为 ArrayList
*
* @param elements 输入字节数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: ByteArray): ArrayList<Byte> { fun newArrayLists(elements: ByteArray): ArrayList<Byte> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将短整型数组转换为 ArrayList
*
* @param elements 输入短整型数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: ShortArray): ArrayList<Short> { fun newArrayLists(elements: ShortArray): ArrayList<Short> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将整型数组转换为 ArrayList
*
* @param elements 输入整型数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: IntArray): ArrayList<Int> { fun newArrayLists(elements: IntArray): ArrayList<Int> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将长整型数组转换为 ArrayList
*
* @param elements 输入长整型数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: LongArray): ArrayList<Long> { fun newArrayLists(elements: LongArray): ArrayList<Long> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将浮点数组转换为 ArrayList
*
* @param elements 输入浮点数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: FloatArray): ArrayList<Float> { fun newArrayLists(elements: FloatArray): ArrayList<Float> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将双精度浮点数组转换为 ArrayList
*
* @param elements 输入双精度浮点数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: DoubleArray): ArrayList<Double> { fun newArrayLists(elements: DoubleArray): ArrayList<Double> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将布尔数组转换为 ArrayList
*
* @param elements 输入布尔数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: BooleanArray): ArrayList<Boolean> { fun newArrayLists(elements: BooleanArray): ArrayList<Boolean> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 将字符数组转换为 ArrayList
*
* @param elements 输入字符数组
* @return 转换后的 ArrayList
*/
fun newArrayLists(elements: CharArray): ArrayList<Char> { fun newArrayLists(elements: CharArray): ArrayList<Char> {
return ArrayList(elements.toList()) return ArrayList(elements.toList())
} }
/**
* 创建一个新的 CopyOnWriteArrayList 实例
*
* @param T 元素类型
* @return 新创建的 CopyOnWriteArrayList
*/
fun <T> newCopyOnWriteArrayList(): java.util.concurrent.CopyOnWriteArrayList<T> { fun <T> newCopyOnWriteArrayList(): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList() return java.util.concurrent.CopyOnWriteArrayList()
} }
/**
* 使用可变参数创建一个新的 CopyOnWriteArrayList 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 CopyOnWriteArrayList
*/
fun <T> newCopyOnWriteArrayList(vararg elements: T): java.util.concurrent.CopyOnWriteArrayList<T> { fun <T> newCopyOnWriteArrayList(vararg elements: T): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList(elements.asList()) return java.util.concurrent.CopyOnWriteArrayList(elements.asList())
} }
/**
* 将集合转换为新的 CopyOnWriteArrayList 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 CopyOnWriteArrayList
*/
fun <T> newCopyOnWriteArrayList(elements: Collection<T>): java.util.concurrent.CopyOnWriteArrayList<T> { fun <T> newCopyOnWriteArrayList(elements: Collection<T>): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList(elements) return java.util.concurrent.CopyOnWriteArrayList(elements)
} }
/**
* 创建一个新的 Stack 实例
*
* @param T 元素类型
* @return 新创建的 Stack
*/
fun <T> newStack(): Stack<T> { fun <T> newStack(): Stack<T> {
return Stack() return Stack()
} }
/**
* 使用可变参数创建一个新的 Stack 实例
*
* @param T 元素类型
* @param elements 可变参数列表
* @return 新创建的 Stack
*/
fun <T> newStack(vararg elements: T): Stack<T> { fun <T> newStack(vararg elements: T): Stack<T> {
val stack = newStack<T>() val stack = newStack<T>()
stack.addAll(elements.asList()) stack.addAll(elements.asList())
return stack return stack
} }
/**
* 将集合转换为新的 Stack 实例
*
* @param T 元素类型
* @param elements 输入集合
* @return 新创建的 Stack
*/
fun <T> newStack(elements: Collection<T>): Stack<T> { fun <T> newStack(elements: Collection<T>): Stack<T> {
val stack = newStack<T>() val stack = newStack<T>()
stack.addAll(elements) stack.addAll(elements)
@ -354,22 +745,53 @@ fun <T> newStack(elements: Collection<T>): Stack<T> {
} }
/**
* 创建一个新的 TreeSet 实例并指定比较器
*
* @param T 元素类型
* @param comparator 用于排序的比较器
* @return 新创建的 TreeSet
*/
fun <T> newTreeSet(comparator: Comparator<T>): TreeSet<T> { fun <T> newTreeSet(comparator: Comparator<T>): TreeSet<T> {
return TreeSet(comparator) return TreeSet(comparator)
} }
/**
* 使用可变参数创建一个新的 TreeSet 实例并指定比较器
*
* @param T 元素类型
* @param comparator 用于排序的比较器
* @param elements 可变参数列表
* @return 新创建的 TreeSet
*/
fun <T> newTreeSet(comparator: Comparator<T>, vararg elements: T): TreeSet<T> { fun <T> newTreeSet(comparator: Comparator<T>, vararg elements: T): TreeSet<T> {
val set = newTreeSet(comparator) val set = newTreeSet(comparator)
set.addAll(elements.asList()) set.addAll(elements.asList())
return set return set
} }
/**
* 将集合转换为新的 TreeSet 实例并指定比较器
*
* @param T 元素类型
* @param comparator 用于排序的比较器
* @param elements 输入集合
* @return 新创建的 TreeSet
*/
fun <T> newTreeSet(comparator: Comparator<T>, elements: Collection<T>): TreeSet<T> { fun <T> newTreeSet(comparator: Comparator<T>, elements: Collection<T>): TreeSet<T> {
val set = newTreeSet(comparator) val set = newTreeSet(comparator)
set.addAll(elements) set.addAll(elements)
return set return set
} }
/**
* Iterable 转换为新的 TreeSet 实例并指定比较器
*
* @param T 元素类型
* @param comparator 用于排序的比较器
* @param elements 输入 Iterable
* @return 新创建的 TreeSet
*/
fun <T> newTreeSet(comparator: Comparator<T>, elements: Iterable<T>): TreeSet<T> { fun <T> newTreeSet(comparator: Comparator<T>, elements: Iterable<T>): TreeSet<T> {
val set = newTreeSet(comparator) val set = newTreeSet(comparator)
for (element in elements) { for (element in elements) {
@ -378,32 +800,71 @@ fun <T> newTreeSet(comparator: Comparator<T>, elements: Iterable<T>): TreeSet<T>
return set return set
} }
/**
* Sequence 转换为新的 TreeSet 实例并指定比较器
*
* @param T 元素类型
* @param comparator 用于排序的比较器
* @param elements 输入 Sequence
* @return 新创建的 TreeSet
*/
fun <T> newTreeSet(comparator: Comparator<T>, elements: Sequence<T>): TreeSet<T> { fun <T> newTreeSet(comparator: Comparator<T>, elements: Sequence<T>): TreeSet<T> {
return newTreeSet(comparator, elements.toSet()) return newTreeSet(comparator, elements.toSet())
} }
/**
* 将当前集合转换为新的 CopyOnWriteArrayList 实例
*
* @param T 元素类型
* @return 新创建的 CopyOnWriteArrayList
*/
fun <T> Collection<T>.newCopyOnWriteArrayLists(): java.util.concurrent.CopyOnWriteArrayList<T> { fun <T> Collection<T>.newCopyOnWriteArrayLists(): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList(this) return java.util.concurrent.CopyOnWriteArrayList(this)
} }
/**
* 将当前集合转换为新的 Stack 实例
*
* @param T 元素类型
* @return 新创建的 Stack
*/
fun <T> Collection<T>.newStacks(): Stack<T> { fun <T> Collection<T>.newStacks(): Stack<T> {
val stack = Stack<T>() val stack = Stack<T>()
stack.addAll(this) stack.addAll(this)
return stack return stack
} }
/**
* 将当前集合转换为新的 TreeSet 实例
*
* @param T 元素类型必须实现 Comparable 接口
* @return 新创建的 TreeSet
*/
fun <T> Collection<T>.newTreeSets(): TreeSet<T> where T : Comparable<T> { fun <T> Collection<T>.newTreeSets(): TreeSet<T> where T : Comparable<T> {
val set = TreeSet<T>() val set = TreeSet<T>()
set.addAll(this) set.addAll(this)
return set return set
} }
/**
* 将当前集合转换为新的 TreeSet 实例并指定比较器
*
* @param T 元素类型
* @param comparator 用于排序的比较器
* @return 新创建的 TreeSet
*/
fun <T> Collection<T>.newTreeSets(comparator: Comparator<T>): TreeSet<T> { fun <T> Collection<T>.newTreeSets(comparator: Comparator<T>): TreeSet<T> {
val set = TreeSet(comparator) val set = TreeSet(comparator)
set.addAll(this) set.addAll(this)
return set return set
} }
/**
* Byte 类型的 List 转换为字节数组
*
* @param list 输入的 Byte 列表
* @return 转换后的字节数组
*/
fun toArray(list: List<Byte>): ByteArray { fun toArray(list: List<Byte>): ByteArray {
val arr = ByteArray(list.size) val arr = ByteArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -413,6 +874,12 @@ fun toArray(list: List<Byte>): ByteArray {
} }
/**
* Short 类型的 List 转换为短整型数组
*
* @param list 输入的 Short 列表
* @return 转换后的短整型数组
*/
fun toArray(list: List<Short>): ShortArray { fun toArray(list: List<Short>): ShortArray {
val arr = ShortArray(list.size) val arr = ShortArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -421,6 +888,12 @@ fun toArray(list: List<Short>): ShortArray {
return arr return arr
} }
/**
* Int 类型的 List 转换为整型数组
*
* @param list 输入的 Int 列表
* @return 转换后的整型数组
*/
fun toArray(list: List<Int>): IntArray { fun toArray(list: List<Int>): IntArray {
val arr = IntArray(list.size) val arr = IntArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -429,6 +902,12 @@ fun toArray(list: List<Int>): IntArray {
return arr return arr
} }
/**
* Long 类型的 List 转换为长整型数组
*
* @param list 输入的 Long 列表
* @return 转换后的长整型数组
*/
fun toArray(list: List<Long>): LongArray { fun toArray(list: List<Long>): LongArray {
val arr = LongArray(list.size) val arr = LongArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -437,6 +916,12 @@ fun toArray(list: List<Long>): LongArray {
return arr return arr
} }
/**
* Float 类型的 List 转换为浮点数组
*
* @param list 输入的 Float 列表
* @return 转换后的浮点数组
*/
fun toArray(list: List<Float>): FloatArray { fun toArray(list: List<Float>): FloatArray {
val arr = FloatArray(list.size) val arr = FloatArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -445,6 +930,12 @@ fun toArray(list: List<Float>): FloatArray {
return arr return arr
} }
/**
* Double 类型的 List 转换为双精度浮点数组
*
* @param list 输入的 Double 列表
* @return 转换后的双精度浮点数组
*/
fun toArray(list: List<Double>): DoubleArray { fun toArray(list: List<Double>): DoubleArray {
val arr = DoubleArray(list.size) val arr = DoubleArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -453,6 +944,12 @@ fun toArray(list: List<Double>): DoubleArray {
return arr return arr
} }
/**
* Boolean 类型的 List 转换为布尔数组
*
* @param list 输入的 Boolean 列表
* @return 转换后的布尔数组
*/
fun toArray(list: List<Boolean>): BooleanArray { fun toArray(list: List<Boolean>): BooleanArray {
val arr = BooleanArray(list.size) val arr = BooleanArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -461,6 +958,12 @@ fun toArray(list: List<Boolean>): BooleanArray {
return arr return arr
} }
/**
* Char 类型的 List 转换为字符数组
*
* @param list 输入的 Char 列表
* @return 转换后的字符数组
*/
fun toArray(list: List<Char>): CharArray { fun toArray(list: List<Char>): CharArray {
val arr = CharArray(list.size) val arr = CharArray(list.size)
for (i in list.indices) { for (i in list.indices) {
@ -468,3 +971,23 @@ fun toArray(list: List<Char>): CharArray {
} }
return arr return arr
} }
/**
* 将任意类型的 List 转换为数组
*
* @param T 元素类型
* @param list 输入的 List
* @return 转换后的数组
*/
inline fun <reified T> toArray(list: List<T>): Array<T> {
if (list.isEmpty())
return arrayOf<T>()
return SuperStream.of<T>(list)
.toArray(T::class.java)
}
fun <T> toArray(list: List<T>, clazz: Class<T>): Array<T> {
return SuperStream.of<T>(list)
.toArray(clazz)
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile IsChanged.kt * CurrentFile IsChanged.kt
* LastUpdate 2025-09-15 09:30:37 * LastUpdate 2025-09-19 20:17:07
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */

View File

@ -0,0 +1,273 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ConfigurationProp.kt
* LastUpdate 2025-09-19 11:30:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.configuration
/**
* 配置属性注解用于标记配置类中的字段支持通过命令行参数进行初始化
*
* @param name 配置项的名称默认为空字符串表示使用字段名作为配置项名称
* @param description 配置项的描述信息默认为空字符串
* @param showHelper 是否显示帮助信息默认为 true
*/
@Retention(AnnotationRetention.RUNTIME)
@Target(
AnnotationTarget.TYPE_PARAMETER,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FIELD, // 添加字段支持
AnnotationTarget.PROPERTY // 添加属性支持
)
annotation class ConfigurationProp(val name: String = "", val description: String = "", val showHelper: Boolean = true)
/**
* 根据字段名生成对应的 setter 方法名
*
* @param fieldName 字段名
* @return 对应的 setter 方法名
*/
private fun getSetterName(fieldName: String): String {
return "set" + fieldName.take(1).uppercase() + fieldName.substring(1)
}
/**
* 根据字段名生成对应的 getter 方法名
*
* @param fieldName 字段名
* @return 对应的 getter 方法名
*/
private fun getGetterName(fieldName: String): String {
return "get" + fieldName.take(1).uppercase() + fieldName.substring(1)
}
/**
* 配置初始化器用于解析命令行参数并填充配置对象
*/
open class ConfigurationProps {
companion object {
/**
* 初始化配置类实例并根据命令行参数填充其字段
*
* @param clazz 配置类的 Class 对象
* @param args 命令行参数数组
* @return 初始化后的配置类实例
*/
@JvmStatic
fun <T : ConfigurationProps> init(clazz: Class<T>, args: Array<String>): T {
val mapsArgs = parseArguments(args)
val instance = clazz.getDeclaredConstructor().newInstance()
processFields(clazz, instance, mapsArgs)
return instance
}
/**
* 解析命令行参数将其转换为键值对映射
*
* 支持以下格式
* - `--key=value` `-k=value`键值对形式
* - `--key value` `-k value`键和值分开的形式
* - `--flag` `-f`布尔标志形式默认值为 "true"
*
* @param args 命令行参数数组
* @return 解析后的键值对映射
*/
private fun parseArguments(args: Array<String>): Map<String, List<String>> {
val mapsArgs = mutableMapOf<String, MutableList<String>>()
var i = 0
while (i < args.size) {
val arg = args[i]
when {
arg.startsWith("--") -> {
// 处理 --key=value 格式
if (arg.contains("=")) {
val (key, value) = arg.substring(2).split("=", limit = 2)
mapsArgs.getOrPut(key) { mutableListOf() }.add(value)
}
// 处理 --key value 格式
else if (i + 1 < args.size && !args[i + 1].startsWith("-")) {
val key = arg.substring(2)
val value = args[i + 1]
mapsArgs.getOrPut(key) { mutableListOf() }.add(value)
i++ // 跳过下一个参数
}
// 处理 --flag 格式的布尔标志
else {
val key = arg.substring(2)
mapsArgs.getOrPut(key) { mutableListOf() }.add("true")
}
}
arg.startsWith("-") -> {
// 处理 -k=value 格式
if (arg.contains("=")) {
val (key, value) = arg.substring(1).split("=", limit = 2)
mapsArgs.getOrPut(key) { mutableListOf() }.add(value)
}
// 处理 -k value 格式
else if (i + 1 < args.size && !args[i + 1].startsWith("-")) {
val key = arg.substring(1)
val value = args[i + 1]
mapsArgs.getOrPut(key) { mutableListOf() }.add(value)
i++
}
// 处理 -f 格式的布尔标志
else {
val key = arg.substring(1)
mapsArgs.getOrPut(key) { mutableListOf() }.add("true")
}
}
}
i++
}
return mapsArgs
}
/**
* 处理配置类中的字段根据解析出的参数设置字段值
*
* @param clazz 配置类的 Class 对象
* @param instance 配置类的实例
* @param mapsArgs 解析后的命令行参数映射
*/
private fun <T : ConfigurationProps> processFields(
clazz: Class<T>,
instance: T,
mapsArgs: Map<String, List<String>>
) {
val fields = clazz.declaredFields
for (field in fields) {
val configurationProp = field.getAnnotation(ConfigurationProp::class.java)
if (configurationProp != null) {
val fieldName = configurationProp.name.ifEmpty { field.name }
val values = mapsArgs[fieldName]
if (values != null) {
try {
val setter = clazz.getDeclaredMethod(
getSetterName(field.name),
field.type
)
val value = convertValue(field.type, values, configurationProp)
setter.invoke(instance, value)
} catch (e: Exception) {
println("Warning: Failed to set field ${field.name}: ${e.message}")
}
}
}
}
}
/**
* 将字符串值转换为目标类型
*
* @param type 目标类型
* @param values 字符串值列表
* @param annotation 配置属性注解
* @return 转换后的值
*/
private fun convertValue(
type: Class<*>,
values: List<String>,
annotation: ConfigurationProp
): Any? {
val lastValue = values.lastOrNull() ?: return null
return when (type) {
String::class.java -> lastValue
Integer::class.java, Int::class.java -> try {
lastValue.toInt()
} catch (e: NumberFormatException) {
println("Warning: Invalid integer value '$lastValue'")
null
}
Long::class.java, java.lang.Long::class.java -> try {
lastValue.toLong()
} catch (e: NumberFormatException) {
println("Warning: Invalid long value '$lastValue'")
null
}
Double::class.java, java.lang.Double::class.java -> try {
lastValue.toDouble()
} catch (e: NumberFormatException) {
println("Warning: Invalid double value '$lastValue'")
null
}
Boolean::class.java, java.lang.Boolean::class.java -> when (lastValue.lowercase()) {
"true", "1", "yes", "on" -> true
"false", "0", "no", "off" -> false
else -> {
println("Warning: Invalid boolean value '$lastValue'")
null
}
}
List::class.java -> values
else -> {
println("Warning: Unsupported type ${type.simpleName}")
null
}
}
}
}
fun printHelp() {
val fields = this::class.java.declaredFields
val help = StringBuilder()
for (field in fields) {
val configurationProp = field.getAnnotation(ConfigurationProp::class.java)
if (configurationProp != null && configurationProp.showHelper) {
val fieldName = configurationProp.name.ifEmpty { field.name }
help.append("$fieldName -> 类型: ${field.type.simpleName}")
if (configurationProp.description.isNotEmpty()) {
help.append(" 描述: ${configurationProp.description}")
}
help.append("\n")
}
}
println(help)
}
val fields: Map<String, Any?>
get() {
val fields = this::class.java.declaredFields
val fieldValues = mutableMapOf<String, Any?>()
for (field in fields) {
field.isAccessible = true
val fieldName = field.name
val fieldValue = field.get(this)
fieldValues[fieldName] = fieldValue
}
return fieldValues
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile DtoUtils.kt
* LastUpdate 2025-09-19 13:38:56
* UpdateUser MingLiPro
*/
@file:JvmName("DtoUtils")
package com.mingliqiye.utils.dto
import java.lang.reflect.Field
/**
* 克隆一个对象通过反射创建新实例并复制所有非静态字段值
*
* @param obj 要克隆的对象必须是非空的任意类型实例
* @return 返回一个新的对象实例其字段值与原对象一致
*/
fun <T : Any> clone(obj: T): T {
val clazz = obj.javaClass
val constructor = clazz.getDeclaredConstructor().apply {
isAccessible = true
}
val instance = constructor.newInstance()
// 遍历类及其父类的所有字段进行赋值
var currentClass: Class<*>? = clazz
while (currentClass != null) {
currentClass.declaredFields.forEach { field ->
if (!java.lang.reflect.Modifier.isStatic(field.modifiers)) {
field.isAccessible = true
field.set(instance, field.get(obj))
}
}
currentClass = currentClass.superclass
}
return instance
}
/**
* 定义 DTO 拷贝行为的枚举类型
*/
enum class DotCopyType {
/**
* 表示使用点拷贝.copy方式处理字段
*/
DOT_COPY,
/**
* 表示普通拷贝方式处理字段
*/
COPY
}
/**
* 标注用于控制 DTO 字段拷贝行为的注解
*
* @param type 指定拷贝类型默认为 COPY
*/
@Retention(AnnotationRetention.RUNTIME)
@Target(
AnnotationTarget.TYPE_PARAMETER,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FIELD,
AnnotationTarget.PROPERTY
)
annotation class DtoCopy(val type: DotCopyType = DotCopyType.COPY)
/**
* 将源对象转换为目标 DTO 类型的实例并根据字段名匹配拷贝字段值
*
* @param obj 源对象包含需要被拷贝的数据
* @param dtoClass 目标 DTO Class 对象
* @return 返回一个新的目标 DTO 实例字段值已从源对象拷贝
*/
fun <R : Any> toDto(obj: Any, dtoClass: Class<R>): R {
val instance = dtoClass.getDeclaredConstructor().apply {
isAccessible = true
}.newInstance()
val sourceFields = getAllFields(obj.javaClass)
for (sourceField in sourceFields) {
sourceField.isAccessible = true
val fieldName = sourceField.name
val fieldValue = sourceField.get(obj)
try {
val targetField = dtoClass.getDeclaredField(fieldName).apply {
isAccessible = true
}
if (java.lang.reflect.Modifier.isStatic(targetField.modifiers)) {
continue
}
val ta = targetField.getAnnotation(DtoCopy::class.java)
if (ta != null) {
if (ta.type == DotCopyType.DOT_COPY) {
continue
}
}
targetField.set(instance, fieldValue)
} catch (e: NoSuchFieldException) {
continue
} catch (e: IllegalArgumentException) {
continue
}
}
return instance
}
/**
* 获取指定类及其所有父类中声明的所有字段
*
* @param clazz 起始类对象
* @return 包含所有字段的列表
*/
private fun getAllFields(clazz: Class<*>): List<Field> {
val fields = mutableListOf<Field>()
var currentClass: Class<*>? = clazz
while (currentClass != null && currentClass != Any::class.java) {
fields.addAll(currentClass.declaredFields)
currentClass = currentClass.superclass
}
return fields
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile HashUtils.kt * CurrentFile HashUtils.kt
* LastUpdate 2025-09-17 16:20:57 * LastUpdate 2025-09-19 20:24:33
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("HashUtils") @file:JvmName("HashUtils")
@ -24,6 +24,7 @@
package com.mingliqiye.utils.hash package com.mingliqiye.utils.hash
import com.mingliqiye.utils.base.BASE16
import com.mingliqiye.utils.bcrypt.checkpw import com.mingliqiye.utils.bcrypt.checkpw
import com.mingliqiye.utils.bcrypt.hashpw import com.mingliqiye.utils.bcrypt.hashpw
import java.io.File import java.io.File
@ -70,15 +71,7 @@ fun calculateFileHash(file: File, algorithm: String): String {
* @return 对应的十六进制字符串 * @return 对应的十六进制字符串
*/ */
private fun bytesToHex(bytes: ByteArray): String { private fun bytesToHex(bytes: ByteArray): String {
val hexString = StringBuilder(2 * bytes.size) return BASE16.encode(bytes)
for (b in bytes) {
val hex = Integer.toHexString(0xff and b.toInt())
if (hex.length == 1) {
hexString.append('0')
}
hexString.append(hex)
}
return hexString.toString()
} }
/** /**

View File

@ -0,0 +1,63 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile IO.kt
* LastUpdate 2025-09-20 16:03:14
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.io
fun Any?.println() {
IO.println(this)
}
class IO {
companion object {
@JvmStatic
fun print(vararg args: Any?) {
printA(" ", *args)
}
@JvmStatic
fun println(vararg args: Any?) {
printlnA(" ", *args)
}
@JvmStatic
fun printlnA(sp: String, vararg args: Any?) {
printA(" ", *args)
kotlin.io.println()
}
@JvmStatic
fun printA(sp: String = "", vararg args: Any?) {
if (args.isEmpty()) {
kotlin.io.println()
}
val sb = StringBuilder()
for (i in args.indices) {
sb.append(args[i])
if (i < args.size - 1) sb.append(sp)
}
kotlin.io.print(sb)
}
}
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Loggers.kt * CurrentFile Loggers.kt
* LastUpdate 2025-09-15 22:32:50 * LastUpdate 2025-09-18 09:30:48
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -416,6 +416,6 @@ class MingLiLoggerFactory {
} }
} }
val mingLiLoggerFactory = MingLiLoggerFactory() val mingLiLoggerFactory: MingLiLoggerFactory by lazy { MingLiLoggerFactory() }

View File

@ -16,16 +16,20 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Main.kt * CurrentFile Main.kt
* LastUpdate 2025-09-17 19:07:01 * LastUpdate 2025-09-20 13:22:11
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("Main") @file:JvmName("Main")
package com.mingliqiye.utils package com.mingliqiye.utils.main
import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration
import com.mingliqiye.utils.stream.SuperStream
fun main() { fun main() {
AutoConfiguration.printBanner() AutoConfiguration.printBanner()
val data = SuperStream.of(Array(0) { 1 })
println(data)
} }

View File

@ -0,0 +1,64 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile MetaData.kt
* LastUpdate 2025-09-20 10:45:43
* UpdateUser MingLiPro
*/
@file:JvmName("MetaData")
package com.mingliqiye.utils.metadata
import com.mingliqiye.utils.resource.ResourceUtils
import java.util.stream.Collectors.toMap
fun getMetaData(): Map<String, String> {
return ResourceUtils.getStringResource("/META-INF/meta-data").split("\n").stream().map {
if (it.isBlank()) {
return@map null
}
val split = it.split("=")
if (split.size == 2) {
split[0] to split[1]
} else {
return@map null
}
}.filter { it != null }.collect(toMap({ it!!.first }, { it!!.second }))
}
class MingliUtilsMetaData {
var buildTime: String = ""
var groupId: String = ""
var artifactId: String = ""
var version: String = ""
var buildJdkVersion: String = ""
var author: String = ""
var website: String = ""
}
val mingliUtilsMetaData: MingliUtilsMetaData by lazy {
val metaData = getMetaData()
MingliUtilsMetaData().apply {
buildTime = metaData["buildTime"] ?: ""
groupId = metaData["groupId"] ?: ""
artifactId = metaData["artifactId"] ?: ""
version = metaData["version"] ?: ""
buildJdkVersion = metaData["buildJdkVersion"] ?: ""
author = metaData["author"] ?: ""
website = metaData["website"] ?: ""
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile QueryWrapper.kt
* LastUpdate 2025-09-20 14:21:44
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.mybatisplus
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper
/**
* BaseMapperQuery接口扩展了BaseMapper提供了通用的查询包装器功能
*
* @param T 实体类类型
*/
interface BaseMapperQuery<T> : BaseMapper<T> {
/**
* 创建并返回一个新的QueryWrapper实例
*
* @return QueryWrapper<T> 返回类型化的查询包装器实例
*/
fun queryWrapper(): QueryWrapper<T> {
return QueryWrapper<T>()
}
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile OsPath.kt * CurrentFile OsPath.kt
* LastUpdate 2025-09-15 08:59:15 * LastUpdate 2025-09-18 09:47:43
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -26,9 +26,8 @@ package com.mingliqiye.utils.path
import java.io.File import java.io.File
import java.net.URI import java.net.URI
import java.nio.file.* import java.nio.file.Path
import java.util.* import java.nio.file.Paths
import java.util.function.Consumer
class OsPath private constructor(private val path: Path) : Path by path { class OsPath private constructor(private val path: Path) : Path by path {
@ -58,48 +57,4 @@ class OsPath private constructor(private val path: Path) : Path by path {
return OsPath(Paths.get("")) return OsPath(Paths.get(""))
} }
} }
override fun getParent(): Path? {
var parent = path.parent
if (parent == null) {
parent = path.toAbsolutePath().parent
}
return parent
}
override fun toRealPath(vararg options: LinkOption): Path {
return OsPath(path.toRealPath(*options))
}
override fun register(watcher: WatchService, vararg events: WatchEvent.Kind<*>): WatchKey {
return path.register(watcher, *events)
}
override fun register(
watcher: WatchService,
events: Array<out WatchEvent.Kind<*>>,
vararg modifiers: WatchEvent.Modifier
): WatchKey {
return path.register(watcher, events, *modifiers)
}
override fun iterator(): MutableIterator<Path> {
return path.iterator()
}
override fun compareTo(other: Path): Int {
return path.compareTo(other)
}
override fun toString(): String {
return path.toString()
}
override fun forEach(action: Consumer<in Path>) {
path.forEach(action)
}
override fun spliterator(): Spliterator<Path> {
return path.spliterator()
}
} }

View File

@ -0,0 +1,87 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ResourceUtils.kt
* LastUpdate 2025-09-20 10:26:47
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.resource
import java.io.IOException
class ResourceUtils {
companion object {
@JvmStatic
@Throws(IOException::class)
fun getResource(resourceName: String): ByteArray {
return getResource(resourceName, ResourceUtils::class.java)
}
@JvmStatic
@Throws(IOException::class)
fun getResource(resourceName: String, clazz: Class<*>): ByteArray {
return clazz.getResourceAsStream(resourceName)?.use {
it.readBytes()
} ?: throw IOException("Resource not found: $resourceName")
}
@JvmStatic
@Throws(IOException::class)
fun getStringResource(resourceName: String): String {
return getStringResource(resourceName, ResourceUtils::class.java)
}
@JvmStatic
@Throws(IOException::class)
fun getStringResource(resourceName: String, clazz: Class<*>): String {
return clazz.getResourceAsStream(resourceName)?.use {
it.readBytes().toString(charset = Charsets.UTF_8)
} ?: throw IOException("Resource not found: $resourceName")
}
@JvmStatic
@Throws(IOException::class)
fun getStringResourceCallers(resourceName: String): String {
return getStringResource(resourceName, getCallerClass())
}
@JvmStatic
@Throws(IOException::class)
fun getResourceCallers(resourceName: String): ByteArray {
return getResource(resourceName, getCallerClass())
}
private fun getCallerClass(): Class<*> {
val stackTrace = Thread.currentThread().stackTrace
for (i in 2 until stackTrace.size) {
val className = stackTrace[i].className
try {
val clazz = Class.forName(className)
if (clazz != ResourceUtils::class.java && clazz != Companion::class.java) {
return clazz
}
} catch (e: ClassNotFoundException) {
continue
}
}
return ResourceUtils::class.java
}
}
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile AesUtils.kt * CurrentFile AesUtils.kt
* LastUpdate 2025-09-15 22:32:50 * LastUpdate 2025-09-19 20:18:09
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -51,10 +51,4 @@ fun encryptAesGcmNoPadding(src: String, key: String, iv: ByteArray): ByteArray {
return encryptAesGcmNoPadding(src.toByteArray(), key.toByteArray(), iv) return encryptAesGcmNoPadding(src.toByteArray(), key.toByteArray(), iv)
} }
fun main() {
val iv = getRandomBytes(16)
println(encryptAesGcmNoPadding("mingliqiye", "key", iv))
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile AutoConfiguration.kt * CurrentFile AutoConfiguration.kt
* LastUpdate 2025-09-15 22:20:25 * LastUpdate 2025-09-20 10:47:00
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -34,7 +34,7 @@ import java.io.IOException
@org.springframework.boot.autoconfigure.AutoConfiguration @org.springframework.boot.autoconfigure.AutoConfiguration
@ComponentScan( @ComponentScan(
"com.mingliqiye.utils.bean.springboot", "com.mingliqiye.utils.springboot.bean",
"com.mingliqiye.utils.springboot.converters" "com.mingliqiye.utils.springboot.converters"
) )
open class AutoConfiguration { open class AutoConfiguration {
@ -54,10 +54,7 @@ open class AutoConfiguration {
fun printBanner() { fun printBanner() {
val bannerBuilder = StringBuilder(banner) val bannerBuilder = StringBuilder(banner)
try { try {
val inputStream = AutoConfiguration::class.java.getResourceAsStream("/META-INF/meta-data") val inputStream = AutoConfiguration::class.java.getResourceAsStream("/META-INF/meta-data") ?: return
if (inputStream == null) {
return
}
inputStream.use { stream -> inputStream.use { stream ->
var readlen: Int var readlen: Int
val buffer = ByteArray(1024) val buffer = ByteArray(1024)

View File

@ -16,11 +16,11 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile SpringBeanUtils.kt * CurrentFile SpringBeanUtils.kt
* LastUpdate 2025-09-15 22:32:50 * LastUpdate 2025-09-19 20:07:08
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.bean.springboot package com.mingliqiye.utils.springboot.bean
import org.springframework.beans.BeansException import org.springframework.beans.BeansException
import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContext

View File

@ -1,122 +0,0 @@
/*
* Copyright 2025 mingliqiye
*
* 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.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile SuperStream.kt
* LastUpdate 2025-09-15 17:17:48
* UpdateUser MingLiPro
*/
@file:JvmName("Colls")
package com.mingliqiye.utils.stream
import java.util.stream.Collector
import java.util.stream.Collectors
import java.util.stream.Stream
class SuperStream<T> private constructor(val stream: Stream<T>) : Stream<T> by stream {
companion object {
@JvmStatic
fun <T> of(stream: Stream<T>): SuperStream<T> {
return SuperStream(stream)
}
@JvmStatic
fun <T> of(collection: Collection<T>): SuperStream<T> {
return SuperStream(collection.stream())
}
@JvmStatic
fun <T : Map<K, V>, K, V> of(map: T): SuperStream<Map.Entry<K, V>> {
return of(map.entries)
}
@JvmStatic
fun <T> of(vararg array: T): SuperStream<T> {
return of(array.toList())
}
@JvmStatic
fun <T> of(iterator: Iterator<T>): SuperStream<T> {
val data = ArrayList<T>(20)
while (iterator.hasNext()) {
data.add(iterator.next())
}
return of(data)
}
}
}
interface Gettable<T> {
fun get(): T
}
interface KeyGettable<T> : Gettable<T> {
fun getKey(): T
override fun get(): T {
return getKey()
}
}
interface IdGettable<T> : Gettable<T> {
fun getId(): T
override fun get(): T {
return getId()
}
}
fun <T> getThis(t: T): T {
return t
}
fun <T, U> toMapValueThis(valueMapper: java.util.function.Function<in T, out U>): Collector<T, *, Map<T, U>> {
return Collectors.toMap(
java.util.function.Function<T, T> { it },
valueMapper
) as Collector<T, *, Map<T, U>>
}
fun <T, K> toMap(keyMapper: java.util.function.Function<in T, out K>): Collector<T, *, Map<K, T>> {
return Collectors.toMap(
keyMapper,
java.util.function.Function<T, T> { it },
) as Collector<T, *, Map<K, T>>
}
fun <K> toMapGet(): Collector<Gettable<K>, *, Map<K, Gettable<K>>> {
return Collectors.toMap(
java.util.function.Function<Gettable<K>, K> { it.get() },
java.util.function.Function<Gettable<K>, Gettable<K>> { it },
) as Collector<Gettable<K>, *, Map<K, Gettable<K>>>
}
fun <K, V> toMap(): Collector<Map.Entry<K, V>, *, Map<K, V>> {
return Collectors.toMap(
{ entry: Map.Entry<K, V> -> entry.key },
{ entry: Map.Entry<K, V> -> entry.value }
) as Collector<Map.Entry<K, V>, *, Map<K, V>>
}
fun <T> toList(): Collector<T, *, List<T>> {
return Collectors.toList<T>()
}
fun <T> toSet(): Collector<T, *, Set<T>> {
return Collectors.toSet<T>()
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile StringUtils.kt * CurrentFile StringUtils.kt
* LastUpdate 2025-09-17 21:09:10 * LastUpdate 2025-09-18 09:26:41
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("StringUtils") @file:JvmName("StringUtils")
@ -166,12 +166,51 @@ fun String.stringBuilder(): java.lang.StringBuilder {
return StringBuilder(this) return StringBuilder(this)
} }
/**
* 将字符串按照指定分隔符进行分割
* @param str 需要分割的字符串
* @param separator 分割符
* @return 分割后的字符串列表
*/
fun split(str: String, separator: String): List<String> { fun split(str: String, separator: String): List<String> {
return str.split(separator) return str.split(separator)
} }
fun List<String>.join(separator: String): String { /**
return this.joinToString(separator) * 将列表中的元素使用指定分隔符连接成字符串
* @param separator 连接分隔符
* @param getstring 转换函数将列表元素转换为字符串默认使用toString()方法
* @return 连接后的字符串
*/
fun <T> List<T>.join(separator: String, getstring: (T) -> String = { it.toString() }): String {
// 使用StringBuilder构建结果字符串
val sb = StringBuilder()
for (i in this.indices) {
sb.append(this[i])
// 除了最后一个元素外,都在后面添加分隔符
if (i != this.size - 1) {
sb.append(separator)
}
}
return sb.toString()
}
/**
* 使用当前字符串作为分隔符将列表中的元素连接成字符串
* @param list 需要连接的元素列表
* @param getstring 转换函数将列表元素转换为字符串默认使用toString()方法
* @return 连接后的字符串
*/
fun <T> String.join(list: List<T>, getstring: (T) -> String = { it.toString() }): String {
// 使用StringBuilder构建结果字符串
val sb = StringBuilder()
for (i in list.indices) {
sb.append(getstring(list[i]))
// 除了最后一个元素外,都在后面添加当前字符串作为分隔符
if (i != list.size - 1) {
sb.append(this)
}
}
return sb.toString()
} }

View File

@ -16,12 +16,13 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile UUID.kt * CurrentFile UUID.kt
* LastUpdate 2025-09-17 16:27:32 * LastUpdate 2025-09-19 20:22:27
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.uuid package com.mingliqiye.utils.uuid
import com.mingliqiye.utils.base.BASE256
import com.mingliqiye.utils.base.BASE64 import com.mingliqiye.utils.base.BASE64
import com.mingliqiye.utils.base.BASE91 import com.mingliqiye.utils.base.BASE91
import com.mingliqiye.utils.random.randomByteSecure import com.mingliqiye.utils.random.randomByteSecure
@ -66,6 +67,11 @@ class UUID : Serializable {
return UUID(BASE64.decode(baseShortString)) return UUID(BASE64.decode(baseShortString))
} }
@JvmStatic
fun ofBase256ShortString(baseShortString: String): UUID {
return UUID(BASE256.decode(baseShortString))
}
@JvmStatic @JvmStatic
fun ofBase91ShortString(baseShortString: String): UUID { fun ofBase91ShortString(baseShortString: String): UUID {
return UUID(BASE91.decode(baseShortString)) return UUID(BASE91.decode(baseShortString))
@ -656,6 +662,10 @@ class UUID : Serializable {
return BASE91.encode(data) return BASE91.encode(data)
} }
fun getBase256ShortString(): String {
return BASE256.encode(data)
}
/** /**
* 提取 UUID V1 中的 MAC 地址 * 提取 UUID V1 中的 MAC 地址
* *