refactor(mingli-utils):重构集合工具类并添加新功能

- 重写 Collection 类,使用 Kotlin 语法和特性优化代码结构
- 添加新方法以支持数组和集合之间的转换
- 新增 CopyOnWriteArrayList、Stack 和 TreeSet 相关方法
-优化现有方法,提高代码可读性和性能
- 删除未使用的 ForEach 导入
-调整 build.gradle.kts 中的依赖项
This commit is contained in:
Armamem0t 2025-09-15 09:30:41 +08:00
parent d6a2117b58
commit dc129c016f
Signed by: minglipro
GPG Key ID: 5F355A77B22AA93B
37 changed files with 1507 additions and 19308 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-13 10:11:22 * LastUpdate 2025-09-14 22:32:52
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -78,7 +78,7 @@ dependencies {
implementation("org.mindrot:jbcrypt:0.4") implementation("org.mindrot:jbcrypt:0.4")
implementation("org.jetbrains:annotations:24.0.0") implementation("org.jetbrains:annotations:24.0.0")
compileOnly("net.java.dev.jna:jna:5.17.0") compileOnly("net.java.dev.jna:jna:5.17.0")
implementation("jakarta.annotation:jakarta.annotation-api:2.1.1") //implementation("jakarta.annotation:jakarta.annotation-api:2.1.1")
implementation("org.slf4j:slf4j-api:2.0.17") implementation("org.slf4j:slf4j-api:2.0.17")
implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1") implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1")
@ -96,7 +96,6 @@ tasks.withType<JavaExec>().configureEach {
) )
} }
tasks.withType<org.gradle.jvm.tasks.Jar> { tasks.withType<org.gradle.jvm.tasks.Jar> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest { manifest {

View File

@ -16,10 +16,10 @@
# ProjectName mingli-utils # ProjectName mingli-utils
# ModuleName mingli-utils # ModuleName mingli-utils
# CurrentFile gradle.properties # CurrentFile gradle.properties
# LastUpdate 2025-09-14 22:10:29 # LastUpdate 2025-09-15 09:25:10
# 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=3.3.2 VERSIONS=4.0.0-pre

View File

@ -0,0 +1,30 @@
/*
* 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 Main.java
* LastUpdate 2025-09-15 09:24:07
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils;
public class Main {
public static void main(String[] args) {
MainKt.main();
}
}

View File

@ -1,347 +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 Collection.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.collection;
import com.mingliqiye.utils.stream.SuperStream;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
/**
* 集合工具类提供对列表和数组的常用操作方法
*
* @author MingLiPro
*/
public class Collection {
/**
* 获取集合的第一个元素
*
* @param collection 集合
* @param <T> 元素类型
* @return 第一个元素如果集合为空或为null则返回 null
*/
@Nullable
public static <T> T getFirst(@Nullable java.util.Collection<T> collection) {
if (collection == null || collection.isEmpty()) {
return null;
}
// 对于List类型直接获取第一个元素
if (collection instanceof List) {
return ((List<T>) collection).get(0);
}
// 对于其他Collection类型使用迭代器获取第一个元素
return collection.iterator().next();
}
/**
* 获取数组的第一个元素
*
* @param list 数组不能为空
* @param <T> 元素类型
* @return 第一个元素如果数组为空则返回 null
*/
@Nullable
public static <T> T getFirst(@NotNull T[] list) {
if (list.length == 0) {
return null;
}
return list[0];
}
/**
* 获取集合的最后一个元素
*
* @param collection 集合
* @param <T> 元素类型
* @return 最后一个元素如果集合为空或为null则返回 null
*/
@Nullable
public static <T> T getLast(@Nullable java.util.Collection<T> collection) {
if (collection == null || collection.isEmpty()) {
return null;
}
// 对于List类型直接获取最后一个元素
if (collection instanceof List) {
List<T> list = (List<T>) collection;
return list.get(list.size() - 1);
}
// 对于其他Collection类型需要遍历到最后一个元素
T lastElement = null;
for (T element : collection) {
lastElement = element;
}
return lastElement;
}
/**
* 获取数组的最后一个元素
*
* @param list 数组不能为空
* @param <T> 元素类型
* @return 最后一个元素如果数组为空则返回 null
*/
@Nullable
public static <T> T getLast(@NotNull T[] list) {
if (list.length == 0) {
return null;
}
return list[list.length - 1];
}
/**
* 获取列表中指定索引的元素如果索引超出范围则返回默认值
*
* @param list 列表
* @param index 索引
* @param defaultValue 默认值
* @param <T> 元素类型
* @return 指定索引的元素或默认值
*/
@Nullable
public static <T> T getOrDefault(
@NotNull java.util.Collection<T> list,
int index,
@Nullable T defaultValue
) {
if (index < 0 || index >= list.size()) {
return defaultValue;
}
return SuperStream.of(list).get(index);
}
/**
* 获取集合中指定索引的元素
* 如果索引超出范围则返回null
*
* @param list 集合
* @param index 索引
* @param <T> 元素类型
* @return 指定索引的元素如果索引超出范围则返回null
*/
@Nullable
public static <T> T get(@NotNull java.util.Collection<T> list, int index) {
return getOrDefault(list, index, null);
}
/**
* 获取数组中指定索引的元素如果索引超出范围则返回默认值
*
* @param array 数组
* @param index 索引
* @param defaultValue 默认值
* @param <T> 元素类型
* @return 指定索引的元素或默认值
*/
@Nullable
public static <T> T getOrDefault(
@NotNull T[] array,
int index,
@Nullable T defaultValue
) {
if (index < 0 || index >= array.length) {
return defaultValue;
}
return array[index];
}
/**
* 获取列表的安全子列表自动处理边界情况
*
* @param list 原始列表
* @param fromIndex 起始索引包含
* @param toIndex 结束索引不包含
* @param <T> 元素类型
* @return 子列表
*/
@NotNull
public static <T> List<T> safeSubList(
@NotNull List<T> list,
int fromIndex,
int toIndex
) {
int size = list.size();
if (size == 0) {
return Collections.emptyList();
}
// 调整边界
fromIndex = Math.max(0, fromIndex);
toIndex = Math.min(size, toIndex);
if (fromIndex >= toIndex) {
return Collections.emptyList();
}
return list.subList(fromIndex, toIndex);
}
/**
* 判断列表是否为空或null
*
* @param list 待检查的列表
* @return 如果列表为null或空则返回true否则返回false
*/
public static boolean isEmpty(@Nullable List<?> list) {
return list == null || list.isEmpty();
}
/**
* 判断数组是否为空或null
*
* @param array 待检查的数组
* @return 如果数组为null或空则返回true否则返回false
*/
public static boolean isEmpty(@Nullable Object[] array) {
return array == null || array.length == 0;
}
/**
* 查找列表中第一个满足条件的元素
*
* @param list 列表
* @param predicate 条件谓词
* @param <T> 元素类型
* @return 第一个满足条件的元素如果没有则返回null
*/
@Nullable
public static <T> T findFirst(
@NotNull List<T> list,
@NotNull Predicate<T> predicate
) {
for (T item : list) {
if (predicate.test(item)) {
return item;
}
}
return null;
}
/**
* 查找数组中第一个满足条件的元素
*
* @param array 数组
* @param predicate 条件谓词
* @param <T> 元素类型
* @return 第一个满足条件的元素如果没有则返回null
*/
@Nullable
public static <T> T findFirst(
@NotNull T[] array,
@NotNull Predicate<T> predicate
) {
for (T item : array) {
if (predicate.test(item)) {
return item;
}
}
return null;
}
/**
* 过滤列表中满足条件的元素
*
* @param list 原始列表
* @param predicate 条件谓词
* @param <T> 元素类型
* @return 包含满足条件元素的新列表
*/
@NotNull
public static <T> List<T> filter(
@NotNull List<T> list,
@NotNull Predicate<T> predicate
) {
List<T> result = new ArrayList<>();
for (T item : list) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
}
/**
* 过滤数组中满足条件的元素
*
* @param array 原始数组
* @param predicate 条件谓词
* @param <T> 元素类型
* @return 包含满足条件元素的新列表
*/
@NotNull
public static <T> List<T> filter(
@NotNull T[] array,
@NotNull Predicate<T> predicate
) {
return filter(Arrays.asList(array), predicate);
}
/**
* 将列表转换为数组
*
* @param list 列表
* @param clazz 元素类型class
* @param <T> 元素类型
* @return 转换后的数组
*/
@SuppressWarnings("unchecked")
@NotNull
public static <T> T[] toArray(
@NotNull List<T> list,
@NotNull Class<T> clazz
) {
T[] array = (T[]) java.lang.reflect.Array.newInstance(
clazz,
list.size()
);
return list.toArray(array);
}
/**
* 将集合转换为列表
*
* @param collection 集合
* @param <T> 元素类型
* @return 转换后的列表
*/
@NotNull
public static <T> List<T> toList(
@NotNull java.util.Collection<T> collection
) {
return new ArrayList<>(collection);
}
public static <T> SuperStream<T> toSuperStream(
@NotNull java.util.Collection<T> list
) {
return SuperStream.of(list);
}
}

View File

@ -1,579 +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 ForEach.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.collection;
import com.mingliqiye.utils.functions.P1Function;
import com.mingliqiye.utils.functions.P2Function;
import com.mingliqiye.utils.functions.P3Function;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
/**
* 集合和映射的增强遍历功能
* ListsAMaps 工具类提供对集合和映射的增强遍历功能
* 包含多个重载的 forEach 方法支持带索引的遍历操作<br>
*
* 不可终止的遍历 可以使用 ForEachBreaked
*
* @since 3.0.4
*
* @see com.mingliqiye.utils.collection.ForEachBreaked
* @author MingLiPro
*/
public class ForEach {
/**
* 对给定的可迭代对象执行指定的操作操作包含元素值和索引
* 根据可迭代对象类型选择最优的遍历方式以提高性能
*
* @param iterable 要遍历的可迭代对象
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param <T> 可迭代对象中元素的类型
*/
public static <T> void forEach(
Iterable<T> iterable,
P2Function<? super T, Integer> action
) {
// 参数校验如果集合或操作为空则直接返回
if (iterable == null || action == null) {
return;
}
// 如果集合实现了 RandomAccess 接口 ArrayList使用索引访问优化性能
if (iterable instanceof RandomAccess && iterable instanceof List) {
List<T> list = (List<T>) iterable;
for (int i = 0; i < list.size(); i++) {
action.call(list.get(i), i);
}
}
// 如果是普通 List使用迭代器遍历并手动维护索引
else if (iterable instanceof List) {
int index = 0;
Iterator<T> it = iterable.iterator();
while (it.hasNext()) {
action.call(it.next(), index);
index++;
}
}
// 其他类型的集合使用增强 for 循环并手动维护索引
else {
int index = 0;
for (T element : iterable) {
action.call(element, index);
index++;
}
}
}
/**
* 对给定的可迭代对象执行指定的操作仅处理元素值
* 根据可迭代对象是否实现 RandomAccess 接口选择最优的遍历方式
*
* @param iterable 要遍历的可迭代对象
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param <T> 可迭代对象中元素的类型
*/
public static <T> void forEach(
Iterable<T> iterable,
P1Function<? super T> action
) {
// 参数校验如果集合或操作为空则直接返回
if (iterable == null || action == null) {
return;
}
// 如果集合实现了 RandomAccess 接口使用索引访问提升性能
if (iterable instanceof RandomAccess) {
List<T> list = (List<T>) iterable;
for (int i = 0; i < list.size(); i++) {
action.call(list.get(i));
}
}
// 否则使用增强 for 循环进行遍历
else {
for (T element : iterable) {
action.call(element);
}
}
}
/**
* 对给定的迭代器执行指定的操作仅处理元素值
* @param iterator 要遍历的迭代器
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param <T> 迭代器中元素的类型
*/
public static <T> void forEach(
Iterator<T> iterator,
P2Function<? super T, Integer> action
) {
if (iterator == null || action == null) {
return;
}
int index = 0;
while (iterator.hasNext()) {
action.call(iterator.next(), index);
index++;
}
}
/**
* 对给定的迭代器执行指定的操作处理元素值和索引
* @param iterator 要遍历的迭代器
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param <T> 迭代器中元素的类型
*/
public static <T> void forEach(
Iterator<T> iterator,
P1Function<? super T> action
) {
if (iterator == null || action == null) {
return;
}
while (iterator.hasNext()) {
action.call(iterator.next());
}
}
/**
* 对给定的映射执行指定的操作操作包含键值和索引
* 根据映射类型选择不同的遍历策略
*
* @param map 要遍历的映射
* @param action 要对每个键值对执行的操作接收键值和索引作为参数
* @param <K> 映射中键的类型
* @param <V> 映射中值的类型
*/
public static <K, V> void forEach(
Map<K, V> map,
P3Function<? super K, ? super V, Integer> action
) {
// 参数校验如果映射或操作为空则直接返回
if (map == null || action == null) {
return;
}
// 遍历 TreeMap 的条目集合并传递索引
if (map instanceof TreeMap) {
int index = 0;
for (Map.Entry<K, V> entry : map.entrySet()) {
action.call(entry.getKey(), entry.getValue(), index);
index++;
}
}
// 遍历 ConcurrentMap LinkedHashMap 的条目集合并传递索引
else if (map instanceof ConcurrentMap || map instanceof LinkedHashMap) {
int index = 0;
for (Map.Entry<K, V> entry : map.entrySet()) {
action.call(entry.getKey(), entry.getValue(), index);
index++;
}
}
// 遍历其他类型映射的条目集合并传递索引
else {
int index = 0;
for (Map.Entry<K, V> entry : map.entrySet()) {
action.call(entry.getKey(), entry.getValue(), index);
index++;
}
}
}
/**
* 对给定的映射执行指定的操作仅处理键和值
* 根据映射类型选择不同的遍历策略
*
* @param map 要遍历的映射
* @param action 要对每个键值对执行的操作接收键和值作为参数
* @param <K> 映射中键的类型
* @param <V> 映射中值的类型
*/
public static <K, V> void forEach(
Map<K, V> map,
P2Function<? super K, ? super V> action
) {
// 参数校验如果映射或操作为空则直接返回
if (map == null || action == null) {
return;
}
// 遍历 TreeMap 的条目集合
if (map instanceof TreeMap) {
for (Map.Entry<K, V> entry : map.entrySet()) {
action.call(entry.getKey(), entry.getValue());
}
}
// 如果是 ConcurrentMap LinkedHashMap使用其内置的 forEach 方法
else if (map instanceof ConcurrentMap || map instanceof LinkedHashMap) {
forEach(map.entrySet(), i -> action.call(i.getKey(), i.getValue()));
}
// 遍历其他类型映射的条目集合
else {
for (Map.Entry<K, V> entry : map.entrySet()) {
action.call(entry.getKey(), entry.getValue());
}
}
}
/**
* 对可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的可变参数数组
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
P2Function<? super T, Integer> action,
T... objects
) {
forEach(Lists.newArrayList(objects), action);
}
/**
* 对数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
T[] objects,
P2Function<? super T, Integer> action
) {
forEach(action, objects);
}
/**
* 对数组执行指定的操作仅处理元素值
*
* @param objects 要遍历的数组
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(T[] objects, P1Function<? super T> action) {
forEach(action, objects);
}
/**
* 对可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的可变参数数组
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(P1Function<? super T> action, T... objects) {
forEach(Lists.toList(objects), (t, i) -> action.call(t));
}
/**
* 对整型数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的整型数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
int[] objects,
P2Function<Integer, Integer> action
) {
forEach(action, objects);
}
/**
* 对整型可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的整型可变参数数组
*/
private static void forEach(
P2Function<Integer, Integer> action,
int... objects
) {
forEach(objects, action);
}
/**
* 对整型可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的整型可变参数数组
*/
private static void forEach(P1Function<Integer> action, int... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对字节数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的字节数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
byte[] objects,
P2Function<Byte, Integer> action
) {
forEach(Lists.toList(objects), action);
}
/**
* 对字节可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的字节可变参数数组
*/
private static void forEach(
P2Function<Byte, Integer> action,
byte... objects
) {
forEach(objects, action);
}
/**
* 对字节可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的字节可变参数数组
*/
private static void forEach(P1Function<Byte> action, byte... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对短整型数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的短整型数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
short[] objects,
P2Function<Short, Integer> action
) {
forEach(Lists.toList(objects), action);
}
/**
* 对短整型可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的短整型可变参数数组
*/
private static void forEach(
P2Function<Short, Integer> action,
short... objects
) {
forEach(objects, action);
}
/**
* 对短整型可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的短整型可变参数数组
*/
private static void forEach(P1Function<Short> action, short... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对长整型数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的长整型数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
long[] objects,
P2Function<Long, Integer> action
) {
forEach(action, objects);
}
/**
* 对长整型可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的长整型可变参数数组
*/
private static void forEach(
P2Function<Long, Integer> action,
long... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对长整型可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的长整型可变参数数组
*/
private static void forEach(P1Function<Long> action, long... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对浮点数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的浮点数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
float[] objects,
P2Function<Float, Integer> action
) {
forEach(action, objects);
}
/**
* 对浮点可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的浮点可变参数数组
*/
private static void forEach(
P2Function<Float, Integer> action,
float... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对浮点可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的浮点可变参数数组
*/
private static void forEach(P1Function<Float> action, float... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对双精度浮点数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的双精度浮点数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
double[] objects,
P2Function<Double, Integer> action
) {
forEach(action, objects);
}
/**
* 对双精度浮点可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的双精度浮点可变参数数组
*/
private static void forEach(
P2Function<Double, Integer> action,
double... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对双精度浮点可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的双精度浮点可变参数数组
*/
private static void forEach(P1Function<Double> action, double... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对字符数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的字符数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
char[] objects,
P2Function<Character, Integer> action
) {
forEach(action, objects);
}
/**
* 对字符可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的字符可变参数数组
*/
private static void forEach(
P2Function<Character, Integer> action,
char... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对字符可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的字符可变参数数组
*/
private static void forEach(P1Function<Character> action, char... objects) {
forEach(Lists.toList(objects), action);
}
/**
* 对布尔数组执行指定的操作操作包含元素值和索引
*
* @param objects 要遍历的布尔数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
*/
public static void forEach(
boolean[] objects,
P2Function<Character, Integer> action
) {
forEach(objects, action);
}
/**
* 对布尔可变参数数组执行指定的操作操作包含元素值和索引
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数
* @param objects 要遍历的布尔可变参数数组
*/
private static void forEach(
P2Function<Boolean, Integer> action,
boolean... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对布尔可变参数数组执行指定的操作仅处理元素值
*
* @param action 要对每个元素执行的操作只接收元素值作为参数
* @param objects 要遍历的布尔可变参数数组
*/
private static void forEach(
P1Function<Boolean> action,
boolean... objects
) {
forEach(Lists.toList(objects), action);
}
}

View File

@ -1,656 +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 ForEachBreaked.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.collection;
import com.mingliqiye.utils.functions.P1RFunction;
import com.mingliqiye.utils.functions.P2RFunction;
import com.mingliqiye.utils.functions.P3RFunction;
import java.util.*;
import java.util.Collection;
import java.util.concurrent.ConcurrentMap;
/**
* ForEachBreaked 工具类提供对集合和映射的增强遍历功能支持在遍历过程中中断操作
* 包含多个重载的 forEach 方法支持带索引的遍历操作并且可以在满足条件时提前终止遍历
* <br>
*
* <p>
* return null; // 提前下一次遍历 = continue;
* <p>
* return true; // 提前终止遍历 = break;
* <p>
* return false; // 继续下一次遍历
*
* @author MingLiPro
* @since 3.0.4
*/
public class ForEachBreaked {
/**
* 对给定的集合执行指定的操作操作包含元素值和索引
* 根据集合类型选择最优的遍历方式以提高性能
* 当操作返回 true 遍历将提前终止
*
* @param collection 要遍历的集合可以是 List 或其他 Collection 实现
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param <T> 集合中元素的类型
*/
public static <T> void forEach(
Collection<T> collection,
P2RFunction<? super T, Integer, Boolean> action
) {
// 参数校验如果集合或操作为空则直接返回
if (collection == null || action == null) {
return;
}
// 如果集合实现了 RandomAccess 接口 ArrayList使用索引访问优化性能
if (collection instanceof RandomAccess && collection instanceof List) {
List<T> list = (List<T>) collection;
for (int i = 0; i < list.size(); i++) {
if (action.call(list.get(i), i)) return;
}
}
// 如果是普通 List使用迭代器遍历并手动维护索引
else if (collection instanceof List) {
int index = 0;
Iterator<T> it = collection.iterator();
while (it.hasNext()) {
if (action.call(it.next(), index)) return;
index++;
}
}
// 其他类型的集合使用增强 for 循环并手动维护索引
else {
int index = 0;
for (T element : collection) {
if (action.call(element, index)) return;
index++;
}
}
}
/**
* 对给定的集合执行指定的操作仅处理元素值
* 根据集合是否实现 RandomAccess 接口选择最优的遍历方式
* 当操作返回 true 遍历将提前终止
*
* @param collection 要遍历的集合
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param <T> 集合中元素的类型
*/
public static <T> void forEach(
Collection<T> collection,
P1RFunction<? super T, Boolean> action
) {
// 参数校验如果集合或操作为空则直接返回
if (collection == null || action == null) {
return;
}
// 如果集合实现了 RandomAccess 接口使用索引访问提升性能
if (collection instanceof RandomAccess) {
List<T> list = (List<T>) collection;
for (int i = 0; i < list.size(); i++) {
if (action.call(list.get(i))) return;
}
}
// 否则使用增强 for 循环进行遍历
else {
for (T element : collection) {
if (action.call(element)) return;
}
}
}
/**
* 对给定的映射执行指定的操作操作包含键值和索引
* 根据映射类型选择不同的遍历策略
* 当操作返回 true 遍历将提前终止
*
* @param map 要遍历的映射
* @param action 要对每个键值对执行的操作接收键值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param <K> 映射中键的类型
* @param <V> 映射中值的类型
*/
public static <K, V> void forEach(
Map<K, V> map,
P3RFunction<? super K, ? super V, Integer, Boolean> action
) {
// 参数校验如果映射或操作为空则直接返回
if (map == null || action == null) {
return;
}
// 遍历 TreeMap 的条目集合并传递索引
if (map instanceof TreeMap) {
int index = 0;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (
action.call(entry.getKey(), entry.getValue(), index)
) return;
index++;
}
}
// 遍历 ConcurrentMap LinkedHashMap 的条目集合并传递索引
else if (map instanceof ConcurrentMap || map instanceof LinkedHashMap) {
int index = 0;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (
action.call(entry.getKey(), entry.getValue(), index)
) return;
index++;
}
}
// 遍历其他类型映射的条目集合并传递索引
else {
int index = 0;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (
action.call(entry.getKey(), entry.getValue(), index)
) return;
index++;
}
}
}
/**
* 对给定的映射执行指定的操作仅处理键和值
* 根据映射类型选择不同的遍历策略
* 当操作返回 true 遍历将提前终止
*
* @param map 要遍历的映射
* @param action 要对每个键值对执行的操作接收键和值作为参数返回 Boolean 值决定是否继续遍历
* @param <K> 映射中键的类型
* @param <V> 映射中值的类型
*/
public static <K, V> void forEach(
Map<K, V> map,
P2RFunction<? super K, ? super V, Boolean> action
) {
// 参数校验如果映射或操作为空则直接返回
if (map == null || action == null) {
return;
}
// 遍历 TreeMap 的条目集合
if (map instanceof TreeMap) {
for (Map.Entry<K, V> entry : map.entrySet()) {
if (action.call(entry.getKey(), entry.getValue())) return;
}
}
// 如果是 ConcurrentMap LinkedHashMap使用其内置的 forEach 方法
else if (map instanceof ConcurrentMap || map instanceof LinkedHashMap) {
forEach(map.entrySet(), i -> {
return action.call(i.getKey(), i.getValue());
});
}
// 遍历其他类型映射的条目集合
else {
for (Map.Entry<K, V> entry : map.entrySet()) {
if (action.call(entry.getKey(), entry.getValue())) return;
}
}
}
/**
* 对可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的可变参数数组
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
P2RFunction<? super T, Integer, Boolean> action,
T... objects
) {
forEach(Lists.newArrayList(objects), action);
}
/**
* 对数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
T[] objects,
P2RFunction<? super T, Integer, Boolean> action
) {
forEach(action, objects);
}
/**
* 对迭代器执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param iterator 要遍历的迭代器
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
Iterator<T> iterator,
P2RFunction<? super T, Integer, Boolean> action
) {
if (iterator == null || action == null) {
return;
}
int index = 0;
while (iterator.hasNext()) {
if (action.call(iterator.next(), index)) return;
index++;
}
}
/**
* 对迭代器执行指定的操作操作包含元素值
* 当操作返回 true 遍历将提前终止
*
* @param iterator 要遍历的迭代器
* @param action 要对每个元素执行的操作接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
Iterator<T> iterator,
P1RFunction<? super T, Boolean> action
) {
if (iterator == null || action == null) {
return;
}
while (iterator.hasNext()) {
if (action.call(iterator.next())) return;
}
}
/**
* 对数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的数组
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
T[] objects,
P1RFunction<? super T, Boolean> action
) {
forEach(action, objects);
}
/**
* 对可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的可变参数数组
* @param <T> 数组中元素的类型
*/
public static <T> void forEach(
P1RFunction<? super T, Boolean> action,
T... objects
) {
forEach(Lists.toList(objects), (t, i) -> {
return action.call(t);
});
}
/**
* 对整型数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的整型数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
int[] objects,
P2RFunction<Integer, Integer, Boolean> action
) {
forEach(action, objects);
}
/**
* 对整型可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的整型可变参数数组
*/
private static void forEach(
P2RFunction<Integer, Integer, Boolean> action,
int... objects
) {
forEach(objects, action);
}
/**
* 对整型可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的整型可变参数数组
*/
private static void forEach(
P1RFunction<Integer, Boolean> action,
int... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对字节数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的字节数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
byte[] objects,
P2RFunction<Byte, Integer, Boolean> action
) {
forEach(Lists.toList(objects), action);
}
/**
* 对字节可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的字节可变参数数组
*/
private static void forEach(
P2RFunction<Byte, Integer, Boolean> action,
byte... objects
) {
forEach(objects, action);
}
/**
* 对字节可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的字节可变参数数组
*/
private static void forEach(
P1RFunction<Byte, Boolean> action,
byte... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对短整型数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的短整型数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
short[] objects,
P2RFunction<Short, Integer, Boolean> action
) {
forEach(Lists.toList(objects), action);
}
/**
* 对短整型可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的短整型可变参数数组
*/
private static void forEach(
P2RFunction<Short, Integer, Boolean> action,
short... objects
) {
forEach(objects, action);
}
/**
* 对短整型可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的短整型可变参数数组
*/
private static void forEach(
P1RFunction<Short, Boolean> action,
short... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对长整型数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的长整型数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
long[] objects,
P2RFunction<Long, Integer, Boolean> action
) {
forEach(action, objects);
}
/**
* 对长整型可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的长整型可变参数数组
*/
private static void forEach(
P2RFunction<Long, Integer, Boolean> action,
long... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对长整型可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的长整型可变参数数组
*/
private static void forEach(
P1RFunction<Long, Boolean> action,
long... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对浮点数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的浮点数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
float[] objects,
P2RFunction<Float, Integer, Boolean> action
) {
forEach(action, objects);
}
/**
* 对浮点可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的浮点可变参数数组
*/
private static void forEach(
P2RFunction<Float, Integer, Boolean> action,
float... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对浮点可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的浮点可变参数数组
*/
private static void forEach(
P1RFunction<Float, Boolean> action,
float... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对双精度浮点数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的双精度浮点数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
double[] objects,
P2RFunction<Double, Integer, Boolean> action
) {
forEach(action, objects);
}
/**
* 对双精度浮点可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的双精度浮点可变参数数组
*/
private static void forEach(
P2RFunction<Double, Integer, Boolean> action,
double... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对双精度浮点可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的双精度浮点可变参数数组
*/
private static void forEach(
P1RFunction<Double, Boolean> action,
double... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对字符数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的字符数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
char[] objects,
P2RFunction<Character, Integer, Boolean> action
) {
forEach(action, objects);
}
/**
* 对字符可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的字符可变参数数组
*/
private static void forEach(
P2RFunction<Character, Integer, Boolean> action,
char... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对字符可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的字符可变参数数组
*/
private static void forEach(
P1RFunction<Character, Boolean> action,
char... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对布尔数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param objects 要遍历的布尔数组
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
*/
public static void forEach(
boolean[] objects,
P2RFunction<Character, Integer, Boolean> action
) {
forEach(objects, action);
}
/**
* 对布尔可变参数数组执行指定的操作操作包含元素值和索引
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作接收元素值和索引作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的布尔可变参数数组
*/
private static void forEach(
P2RFunction<Boolean, Integer, Boolean> action,
boolean... objects
) {
forEach(Lists.toList(objects), action);
}
/**
* 对布尔可变参数数组执行指定的操作仅处理元素值
* 当操作返回 true 遍历将提前终止
*
* @param action 要对每个元素执行的操作只接收元素值作为参数返回 Boolean 值决定是否继续遍历
* @param objects 要遍历的布尔可变参数数组
*/
private static void forEach(
P1RFunction<Boolean, Boolean> action,
boolean... objects
) {
forEach(Lists.toList(objects), action);
}
}

View File

@ -1,479 +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 Lists.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.collection;
import com.mingliqiye.utils.random.RandomInt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Lists工具类提供了一系列创建List实现的便捷方法
*
* @author MingLiPro
*/
public class Lists {
/**
* 创建一个空的ArrayList实例
*
* @param <T> 列表元素的类型
* @return 新创建的空ArrayList实例
*/
public static <T> List<T> newArrayList() {
return new ArrayList<>();
}
/**
* 根据可变参数创建一个包含指定元素的ArrayList实例
*
* @param ts 要添加到列表中的元素可以为0个或多个
* @param <T> 列表元素的类型
* @return 包含指定元素的新ArrayList实例
*/
public static <T> List<T> newArrayList(T... ts) {
List<T> list = newArrayList();
list.addAll(Arrays.asList(ts));
return list;
}
/**
* 根据已有列表创建一个新的ArrayList实例
*
* @param list 要复制的列表
* @param <T> 列表元素的类型
* @return 包含原列表所有元素的新ArrayList实例
*/
public static <T> List<T> newArrayList(List<T> list) {
List<T> newList = newArrayList();
newList.addAll(list);
return newList;
}
/**
* 根据可迭代对象创建一个ArrayList实例
*
* @param iterable 可迭代对象
* @param <T> 列表元素的类型
* @return 包含可迭代对象中所有元素的新ArrayList实例
*/
public static <T> List<T> newArrayList(Iterable<T> iterable) {
List<T> list = newArrayList();
for (T t : iterable) {
list.add(t);
}
return list;
}
/**
* 创建一个指定初始容量的空ArrayList实例
*
* @param size 初始容量大小
* @param <T> 列表元素的类型
* @return 指定初始容量的空ArrayList实例
*/
public static <T> List<T> newArrayList(int size) {
return new ArrayList<>(size);
}
/**
* 创建一个指定大小并用单个元素填充的ArrayList实例
*
* @param size 列表大小
* @param t 用于填充列表的元素
* @param <T> 列表元素的类型
* @return 指定大小且所有元素都相同的ArrayList实例
*/
public static <T> List<T> newArrayList(int size, T t) {
List<T> list = newArrayList(size);
for (int i = 0; i < size; i++) {
list.add(t);
}
return list;
}
/**
* 创建一个指定大小并交替使用两个元素填充的ArrayList实例
*
* @param size 列表大小
* @param t 第一个填充元素索引为偶数时使用
* @param t1 第二个填充元素索引为奇数时使用
* @param <T> 列表元素的类型
* @return 指定大小且交替填充两个元素的ArrayList实例
*/
public static <T> List<T> newArrayList(int size, T t, T t1) {
List<T> list = newArrayList(size);
for (int i = 0; i < size; i++) {
list.add(i % 2 == 0 ? t : t1);
}
return list;
}
/**
* 创建一个指定大小并循环使用三个元素填充的ArrayList实例
*
* @param size 列表大小
* @param t 第一个填充元素索引模3等于0时使用
* @param t1 第二个填充元素索引模3等于1时使用
* @param t2 第三个填充元素索引模3等于2时使用
* @param <T> 列表元素的类型
* @return 指定大小且循环填充三个元素的ArrayList实例
*/
public static <T> List<T> newArrayList(int size, T t, T t1, T t2) {
List<T> list = newArrayList(size);
for (int i = 0; i < size; i++) {
list.add(i % 3 == 0 ? t : i % 3 == 1 ? t1 : t2);
}
return list;
}
/**
* 创建一个指定大小并循环使用四个元素填充的ArrayList实例
*
* @param size 列表大小
* @param t 第一个填充元素索引模4等于0时使用
* @param t1 第二个填充元素索引模4等于1时使用
* @param t2 第三个填充元素索引模4等于2时使用
* @param t3 第四个填充元素索引模4等于3时使用
* @param <T> 列表元素的类型
* @return 指定大小且循环填充四个元素的ArrayList实例
*/
public static <T> List<T> newArrayList(int size, T t, T t1, T t2, T t3) {
List<T> list = newArrayList(size);
for (int i = 0; i < size; i++) {
list.add(i % 4 == 0 ? t : i % 4 == 1 ? t1 : i % 4 == 2 ? t2 : t3);
}
return list;
}
/**
* 创建一个空的LinkedList实例
*
* @param <T> 列表元素的类型
* @return 新创建的空LinkedList实例
*/
public static <T> List<T> newLinkedList() {
return new LinkedList<>();
}
/**
* 根据可变参数创建一个包含指定元素的LinkedList实例
*
* @param ts 要添加到列表中的元素可以为0个或多个
* @param <T> 列表元素的类型
* @return 包含指定元素的新LinkedList实例
*/
public static <T> List<T> newLinkedList(T... ts) {
List<T> list = newLinkedList();
list.addAll(Arrays.asList(ts));
return list;
}
/**
* 根据已有列表创建一个新的LinkedList实例
*
* @param list 要复制的列表
* @param <T> 列表元素的类型
* @return 包含原列表所有元素的新LinkedList实例
*/
public static <T> List<T> newLinkedList(List<T> list) {
List<T> newList = newLinkedList();
newList.addAll(list);
return newList;
}
/**
* 创建一个空的Vector实例
*
* @param <T> 列表元素的类型
* @return 新创建的空Vector实例
*/
public static <T> List<T> newVector() {
return new Vector<>();
}
/**
* 根据可变参数创建一个包含指定元素的Vector实例
*
* @param ts 要添加到列表中的元素可以为0个或多个
* @param <T> 列表元素的类型
* @return 包含指定元素的新Vector实例
*/
public static <T> List<T> newVector(T... ts) {
List<T> list = newVector();
list.addAll(Arrays.asList(ts));
return list;
}
/**
* 根据已有列表创建一个新的Vector实例
*
* @param list 要复制的列表
* @param <T> 列表元素的类型
* @return 包含原列表所有元素的新Vector实例
*/
public static <T> List<T> newVector(List<T> list) {
List<T> newList = newVector();
newList.addAll(list);
return newList;
}
/**
* 将指定列表中的每个元素转换为字符串表示形式
*
* @param <T> 列表元素的类型
* @param list 要转换的列表不能为空
* @return 包含原列表各元素字符串表示的新列表保持相同的顺序
*/
public static <T> List<String> toStringList(@NotNull List<T> list) {
// 创建与原列表相同大小的新列表用于存储字符串转换结果
List<String> newList = newArrayList(list.size());
for (T t : list) {
newList.add(t == null ? "null" : t.toString());
}
return newList;
}
/**
* 将指定数组中的每个元素转换为字符串表示形式
*
* @param <T> 数组元素的类型
* @param list 要转换的数组不能为空
* @return 包含原数组各元素字符串表示的新字符串数组
*/
public static <T> String[] toStringList(@NotNull T[] list) {
// 创建新的字符串列表用于存储转换后的结果
List<String> newList = newArrayList(list.length);
for (T t : list) {
newList.add(t == null ? "null" : t.toString());
}
return newList.toArray(new String[0]);
}
/**
* 将列表转换为数组
*
* @param ts 要转换的列表
* @param <T> 数组元素的类型
* @return 包含列表中所有元素的数组如果列表为null则返回null
*/
@Nullable
public static <T> T[] toArray(List<T> ts) {
if (ts == null) {
return null;
}
T[] items = (T[]) new Object[ts.size()];
ForEach.forEach(ts, (t, i) -> items[i] = t);
return items;
}
/**
* 将数组转换为列表
*
* @param ts 要转换的数组
* @param <T> 列表元素的类型
* @return 包含数组中所有元素的列表如果数组为null则返回null
*/
// 原始的方法 - 用于引用类型
@Nullable
public static <T> List<T> toList(T[] ts) {
return ts == null ? null : new ArrayList<>(Arrays.asList(ts));
}
@NotNull
public static <T> List<T> toList(Stream<T> ts) {
return ts == null
? newArrayList()
: new ArrayList<>(ts.collect(Collectors.toList()));
}
/**
* 将int数组转换为Integer列表
*
* @param array 要转换的int数组
* @return 包含数组中所有元素的Integer列表如果数组为null则返回null
*/
@Nullable
public static List<Integer> toList(int[] array) {
if (array == null) {
return null;
}
List<Integer> list = new ArrayList<>(array.length);
for (int value : array) {
list.add(value);
}
return list;
}
/**
* 将long数组转换为Long列表
*
* @param array 要转换的long数组
* @return 包含数组中所有元素的Long列表如果数组为null则返回null
*/
@Nullable
public static List<Long> toList(long[] array) {
if (array == null) {
return null;
}
List<Long> list = new ArrayList<>(array.length);
for (long value : array) {
list.add(value);
}
return list;
}
/**
* 将double数组转换为Double列表
*
* @param array 要转换的double数组
* @return 包含数组中所有元素的Double列表如果数组为null则返回null
*/
@Nullable
public static List<Double> toList(double[] array) {
if (array == null) {
return null;
}
List<Double> list = new ArrayList<>(array.length);
for (double value : array) {
list.add(value);
}
return list;
}
/**
* 将float数组转换为Float列表
*
* @param array 要转换的float数组
* @return 包含数组中所有元素的Float列表如果数组为null则返回null
*/
@Nullable
public static List<Float> toList(float[] array) {
if (array == null) {
return null;
}
List<Float> list = new ArrayList<>(array.length);
for (float value : array) {
list.add(value);
}
return list;
}
/**
* 将boolean数组转换为Boolean列表
*
* @param array 要转换的boolean数组
* @return 包含数组中所有元素的Boolean列表如果数组为null则返回null
*/
@Nullable
public static List<Boolean> toList(boolean[] array) {
if (array == null) {
return null;
}
List<Boolean> list = new ArrayList<>(array.length);
for (boolean value : array) {
list.add(value);
}
return list;
}
/**
* 将char数组转换为Character列表
*
* @param array 要转换的char数组
* @return 包含数组中所有元素的Character列表如果数组为null则返回null
*/
@Nullable
public static List<Character> toList(char[] array) {
if (array == null) {
return null;
}
List<Character> list = new ArrayList<>(array.length);
for (char value : array) {
list.add(value);
}
return list;
}
/**
* 将byte数组转换为Byte列表
*
* @param array 要转换的byte数组
* @return 包含数组中所有元素的Byte列表如果数组为null则返回null
*/
@Nullable
public static List<Byte> toList(byte[] array) {
if (array == null) {
return null;
}
List<Byte> list = new ArrayList<>(array.length);
for (byte value : array) {
list.add(value);
}
return list;
}
/**
* 将short数组转换为Short列表
*
* @param array 要转换的short数组
* @return 包含数组中所有元素的Short列表如果数组为null则返回null
*/
@Nullable
public static List<Short> toList(short[] array) {
if (array == null) {
return null;
}
List<Short> list = new ArrayList<>(array.length);
for (short value : array) {
list.add(value);
}
return list;
}
public static <T> List<T> toList(Iterator<T> iterator) {
List<T> list = newArrayList(10);
ForEach.forEach(iterator, item -> list.add(item));
return list;
}
public <T> T getFirst(Collection<T> collectors) {
return com.mingliqiye.utils.collection.Collection.getFirst(collectors);
}
public <T> T getLast(Collection<T> collectors) {
return com.mingliqiye.utils.collection.Collection.getFirst(collectors);
}
public <T> T getAny(Collection<T> collectors) {
return com.mingliqiye.utils.collection.Collection.getOrDefault(
collectors,
RandomInt.randomInt(0, collectors.size()),
null
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +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 Sets.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.collection;
import java.util.*;
/**
* Sets工具类提供了一系列创建Set实现的便捷方法
*
* @author MingLiPro
*/
public class Sets {
/**
* 创建一个空的HashSet实例
*
* @param <T> 集合元素的类型
* @return 新创建的空HashSet实例
*/
public static <T> Set<T> newHashSet() {
return new HashSet<>();
}
/**
* 根据可变参数创建一个包含指定元素的HashSet实例
*
* @param ts 要添加到集合中的元素可以为0个或多个
* @param <T> 集合元素的类型
* @return 包含指定元素的新HashSet实例
*/
public static <T> Set<T> newHashSet(T... ts) {
Set<T> set = newHashSet();
set.addAll(Arrays.asList(ts));
return set;
}
/**
* 根据已有集合创建一个新的HashSet实例
*
* @param set 要复制的集合
* @param <T> 集合元素的类型
* @return 包含原集合所有元素的新HashSet实例
*/
public static <T> Set<T> newHashSet(Set<T> set) {
Set<T> newSet = newHashSet();
newSet.addAll(set);
return newSet;
}
/**
* 根据可迭代对象创建一个HashSet实例
*
* @param iterable 可迭代对象
* @param <T> 集合元素的类型
* @return 包含可迭代对象中所有元素的新HashSet实例
*/
public static <T> Set<T> newHashSet(Iterable<T> iterable) {
Set<T> set = newHashSet();
for (T t : iterable) {
set.add(t);
}
return set;
}
/**
* 创建一个指定初始容量的空HashSet实例
*
* @param size 初始容量大小
* @param <T> 集合元素的类型
* @return 指定初始容量的空HashSet实例
*/
public static <T> Set<T> newHashSet(int size) {
return new HashSet<>(size);
}
/**
* 创建一个空的LinkedHashSet实例
*
* @param <T> 集合元素的类型
* @return 新创建的空LinkedHashSet实例
*/
public static <T> Set<T> newLinkedHashSet() {
return new LinkedHashSet<>();
}
/**
* 根据可变参数创建一个包含指定元素的LinkedHashSet实例
*
* @param ts 要添加到集合中的元素可以为0个或多个
* @param <T> 集合元素的类型
* @return 包含指定元素的新LinkedHashSet实例
*/
public static <T> Set<T> newLinkedHashSet(T... ts) {
Set<T> set = newLinkedHashSet();
set.addAll(Arrays.asList(ts));
return set;
}
/**
* 根据已有集合创建一个新的LinkedHashSet实例
*
* @param set 要复制的集合
* @param <T> 集合元素的类型
* @return 包含原集合所有元素的新LinkedHashSet实例
*/
public static <T> Set<T> newLinkedHashSet(Set<T> set) {
Set<T> newSet = newLinkedHashSet();
newSet.addAll(set);
return newSet;
}
/**
* 创建一个空的TreeSet实例
*
* @param <T> 集合元素的类型必须实现Comparable接口
* @return 新创建的空TreeSet实例
*/
public static <T extends Comparable<T>> Set<T> newTreeSet() {
return new TreeSet<>();
}
/**
* 根据可变参数创建一个包含指定元素的TreeSet实例
*
* @param ts 要添加到集合中的元素可以为0个或多个
* @param <T> 集合元素的类型必须实现Comparable接口
* @return 包含指定元素的新TreeSet实例
*/
public static <T extends Comparable<T>> Set<T> newTreeSet(T... ts) {
Set<T> set = newTreeSet();
set.addAll(Arrays.asList(ts));
return set;
}
/**
* 根据已有集合创建一个新的TreeSet实例
*
* @param set 要复制的集合
* @param <T> 集合元素的类型必须实现Comparable接口
* @return 包含原集合所有元素的新TreeSet实例
*/
public static <T extends Comparable<T>> Set<T> newTreeSet(Set<T> set) {
Set<T> newSet = newTreeSet();
newSet.addAll(set);
return newSet;
}
}

View File

@ -1,106 +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 IsChanged.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.concurrent;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
/**
* IsChanged 类提供了一个线程安全的包装器用于检测值是否发生变化
* 它基于 AtomicReference 实现适用于需要监控数据变更的并发场景
*
* @param <T> 泛型类型表示被包装的数据类型
* @author MingLiPro
*/
public class IsChanged<T> {
/**
* 使用 AtomicReference 来保证对数据的原子操作
*/
private final AtomicReference<T> atomicReferenceData;
/**
* 默认构造函数初始化数据为 null
*/
public IsChanged() {
this(null);
}
/**
* 带参数的构造函数使用指定的初始值初始化
*
* @param data 初始数据值
*/
public IsChanged(T data) {
atomicReferenceData = new AtomicReference<>(data);
}
/**
* 设置新的数据值不检查是否发生变化
*
* @param data 要设置的新数据值
*/
public void set(T data) {
atomicReferenceData.set(data);
}
/**
* 获取当前数据值
*
* @return 当前数据值
*/
public T get() {
return atomicReferenceData.get();
}
/**
* 设置新的数据值并返回旧的数据值
*
* @param data 要设置的新数据值
* @return 设置前的旧数据值
*/
public T setAndGet(T data) {
return atomicReferenceData.getAndSet(data);
}
/**
* 设置新的数据值如果新值与当前值不同则更新并返回 true否则返回 false
* 使用 CAS(Compare-And-Swap) 操作确保线程安全
*
* @param data 要设置的新数据值
* @return 如果值发生变化返回 true否则返回 false
*/
public boolean setAndChanged(T data) {
T currentData;
do {
currentData = get();
// 如果新值与当前值相等则认为没有变化直接返回 false
if (Objects.equals(data, currentData)) {
return false;
}
// 使用 CAS 操作尝试更新值如果失败则重试
} while (!atomicReferenceData.compareAndSet(currentData, data));
// 成功更新值返回 true 表示发生了变化
return true;
}
}

View File

@ -1,105 +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 ThreadLocalDataHolder.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.data;
/**
* 泛型线程局部变量持有器
* <p>
* 封装了 ThreadLocal 的常用操作提供更便捷的 API 来管理线程本地变量
*
* @param <T> 存储的数据类型
* @author MingLiPro
*/
public class ThreadLocalDataHolder<T> {
private final ThreadLocal<T> threadLocal;
/**
* 构造函数初始化 ThreadLocal 实例
*/
public ThreadLocalDataHolder() {
this.threadLocal = new ThreadLocal<>();
}
/**
* 获取当前线程存储的值
*
* @return 当前线程存储的值如果没有则返回null
*/
public T get() {
return threadLocal.get();
}
/**
* 设置当前线程的值
*
* @param value 要存储的值
*/
public void set(T value) {
threadLocal.set(value);
}
/**
* 移除当前线程存储的值
* <p>
* 防止内存泄漏使用完毕后应调用此方法清理资源
*/
public void remove() {
threadLocal.remove();
}
/**
* 获取当前线程存储的值如果不存在则返回默认值
*
* @param defaultValue 默认值
* @return 当前线程存储的值或默认值
*/
public T getOrDefault(T defaultValue) {
T value = threadLocal.get();
return value != null ? value : defaultValue;
}
/**
* 安全获取值避免NPE
* <p>
* 在某些异常情况下防止抛出异常直接返回 null
*
* @return 值或null
*/
public T safeGet() {
try {
return threadLocal.get();
} catch (Exception e) {
return null;
}
}
/**
* 检查当前线程是否有值
*
* @return 是否有值
*/
public boolean isPresent() {
return threadLocal.get() != null;
}
}

View File

@ -1,368 +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 FileUtil.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.file;
import com.mingliqiye.utils.string.StringUtils;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
/**
* 文件工具类提供常用的文件操作方法
*
* @author MingLiPro
*/
public class FileUtil {
/**
* 默认字符集
*/
@Getter
@Setter
private static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
/**
* 读取文件内容为字符串
*
* @param filePath 文件路径
* @return 文件内容字符串
* @throws IOException 读取文件时发生错误
*/
public static String readFileToString(String filePath) throws IOException {
return readFileToString(filePath, DEFAULT_CHARSET);
}
/**
* 读取文件内容为字符串
*
* @param filePath 文件路径
* @param charset 字符集
* @return 文件内容字符串
* @throws IOException 读取文件时发生错误
*/
public static String readFileToString(String filePath, Charset charset)
throws IOException {
Path path = Paths.get(filePath);
byte[] bytes = Files.readAllBytes(path);
return new String(bytes, charset);
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 要写入的内容
* @throws IOException 写入文件时发生错误
*/
public static void writeStringToFile(String filePath, String content)
throws IOException {
writeStringToFile(filePath, content, DEFAULT_CHARSET);
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 要写入的内容
* @param charset 字符集
* @throws IOException 写入文件时发生错误
*/
public static void writeStringToFile(
String filePath,
String content,
Charset charset
) throws IOException {
Path path = Paths.get(filePath);
if (path.getParent() != null) {
Files.createDirectories(path.getParent());
}
Files.write(path, content.getBytes(charset));
}
/**
* 读取文件内容为字符串列表按行分割
*
* @param filePath 文件路径
* @return 文件内容按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
public static List<String> readLines(String filePath) throws IOException {
return readLines(filePath, DEFAULT_CHARSET);
}
/**
* 读取文件内容为字符串列表按行分割
*
* @param filePath 文件路径
* @param charset 字符集
* @return 文件内容按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
public static List<String> readLines(String filePath, Charset charset)
throws IOException {
Path path = Paths.get(filePath);
return Files.readAllLines(path, charset);
}
/**
* 将字符串列表写入文件每行一个元素
*
* @param filePath 文件路径
* @param lines 要写入的行内容列表
* @throws IOException 写入文件时发生错误
*/
public static void writeLines(String filePath, List<String> lines)
throws IOException {
writeLines(filePath, lines, DEFAULT_CHARSET);
}
/**
* 将字符串列表写入文件每行一个元素
*
* @param filePath 文件路径
* @param lines 要写入的行内容列表
* @param charset 字符集
* @throws IOException 写入文件时发生错误
*/
public static void writeLines(
String filePath,
List<String> lines,
Charset charset
) throws IOException {
Path path = Paths.get(filePath);
Files.createDirectories(path.getParent());
Files.write(path, lines, charset);
}
/**
* 复制文件
*
* @param sourcePath 源文件路径
* @param targetPath 目标文件路径
* @throws IOException 复制文件时发生错误
*/
public static void copyFile(String sourcePath, String targetPath)
throws IOException {
Path source = Paths.get(sourcePath);
Path target = Paths.get(targetPath);
Files.createDirectories(target.getParent());
Files.copy(source, target);
}
/**
* 删除文件
*
* @param filePath 文件路径
* @return 如果文件删除成功返回true否则返回false
*/
public static boolean deleteFile(String filePath) {
try {
Path path = Paths.get(filePath);
return Files.deleteIfExists(path);
} catch (IOException e) {
return false;
}
}
/**
* 检查文件是否存在
*
* @param filePath 文件路径
* @return 如果文件存在返回true否则返回false
*/
public static boolean exists(String filePath) {
Path path = Paths.get(filePath);
return Files.exists(path);
}
/**
* 获取文件大小
*
* @param filePath 文件路径
* @return 文件大小字节如果文件不存在返回-1
*/
public static long getFileSize(String filePath) {
try {
Path path = Paths.get(filePath);
return Files.size(path);
} catch (IOException e) {
return -1;
}
}
/**
* 创建目录
*
* @param dirPath 目录路径
* @return 如果目录创建成功返回true否则返回false
*/
public static boolean createDirectory(String dirPath) {
try {
Path path = Paths.get(dirPath);
Files.createDirectories(path);
return true;
} catch (IOException e) {
return false;
}
}
/**
* 获取文件扩展名
*
* @param fileName 文件名
* @return 文件扩展名不包含点号如果无扩展名返回空字符串
*/
public static String getFileExtension(String fileName) {
if (StringUtils.isEmpty(fileName)) {
return "";
}
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex == -1 || lastDotIndex == fileName.length() - 1) {
return "";
}
return fileName.substring(lastDotIndex + 1);
}
/**
* 获取不带扩展名的文件名
*
* @param fileName 文件名
* @return 不带扩展名的文件名
*/
public static String getFileNameWithoutExtension(String fileName) {
if (StringUtils.isEmpty(fileName)) {
return "";
}
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex == -1) {
return fileName;
}
return fileName.substring(0, lastDotIndex);
}
/**
* 读取文件内容为字节数组
*
* @param filePath 文件路径
* @return 文件内容的字节数组
* @throws IOException 读取文件时发生错误
*/
public static byte[] readFileToByteArray(String filePath)
throws IOException {
Path path = Paths.get(filePath);
return Files.readAllBytes(path);
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param data 要写入的字节数据
* @throws IOException 写入文件时发生错误
*/
public static void writeByteArrayToFile(String filePath, byte[] data)
throws IOException {
Path path = Paths.get(filePath);
Files.createDirectories(path.getParent());
Files.write(path, data);
}
/**
* 将字节数组追加到文件末尾
*
* @param filePath 文件路径
* @param data 要追加的字节数据
* @throws IOException 追加数据时发生错误
*/
public static void appendByteArrayToFile(String filePath, byte[] data)
throws IOException {
Path path = Paths.get(filePath);
Files.createDirectories(path.getParent());
Files.write(
path,
data,
StandardOpenOption.CREATE,
StandardOpenOption.APPEND
);
}
/**
* 分块读取大文件为字节数组列表
*
* @param filePath 文件路径
* @param chunkSize 每块大小字节
* @return 文件内容按指定大小分割的字节数组列表
* @throws IOException 读取文件时发生错误
*/
public static List<byte[]> readFileToByteArrayChunks(
String filePath,
int chunkSize
) throws IOException {
List<byte[]> chunks = new ArrayList<>();
Path path = Paths.get(filePath);
try (InputStream inputStream = Files.newInputStream(path)) {
byte[] buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] chunk = new byte[bytesRead];
System.arraycopy(buffer, 0, chunk, 0, bytesRead);
chunks.add(chunk);
}
}
return chunks;
}
/**
* 将字节数组列表写入文件
*
* @param filePath 文件路径
* @param chunks 字节数组列表
* @throws IOException 写入文件时发生错误
*/
public static void writeByteArrayChunksToFile(
String filePath,
List<byte[]> chunks
) throws IOException {
Path path = Paths.get(filePath);
Files.createDirectories(path.getParent());
try (OutputStream outputStream = Files.newOutputStream(path)) {
for (byte[] chunk : chunks) {
outputStream.write(chunk);
}
}
}
}

View File

@ -1,69 +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 Response.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.http;
import com.mingliqiye.utils.time.DateTime;
import com.mingliqiye.utils.time.Formatter;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@ToString
@EqualsAndHashCode
@Getter
public class Response<T> {
private final String time = DateTime.now().format(
Formatter.STANDARD_DATETIME_MILLISECOUND7
);
private String message;
private T data;
private int statusCode;
public Response(String message, T data, int statusCode) {
this.message = message;
this.data = data;
this.statusCode = statusCode;
}
public static <T> Response<T> ok(T data) {
return new Response<>("操作成功", data, 200);
}
public Response<T> setMessage(String message) {
this.message = message;
return this;
}
public Response<T> setData(T data) {
this.data = data;
return Response.ok(getData())
.setMessage(getMessage())
.setStatusCode(getStatusCode());
}
public Response<T> setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Range.java * CurrentFile Range.java
* LastUpdate 2025-09-14 22:12:16 * LastUpdate 2025-09-15 09:22:02
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -219,4 +219,9 @@ public class Range
public @NotNull Integer getStart() { public @NotNull Integer getStart() {
return start; return start;
} }
@Override
public String toString() {
return String.format("Range(start=%s,end=%s,step=%s)", start, end, step);
}
} }

View File

@ -1,80 +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 Pseudocryptography.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.minecraft.pe.json;
import com.mingliqiye.utils.collection.ForEach;
import com.mingliqiye.utils.file.FileUtil;
import com.mingliqiye.utils.json.JsonApi;
import com.mingliqiye.utils.json.JsonTypeReference;
import com.mingliqiye.utils.string.StringUtils;
import lombok.val;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Pseudocryptography {
private final JsonApi jsonApi;
public Pseudocryptography(JsonApi jsonApi) {
this.jsonApi = jsonApi;
}
private Object prossed(Object object) {
if (object instanceof Map) {
System.out.println(object.getClass());
val map = new HashMap<>((Map<Object, Object>) object);
val map2 = new HashMap<>(map.size() + 3);
map.forEach((key, value) -> {
if (key instanceof String) {
map2.put(prossed(key), prossed(value));
}
});
return map2;
} else if (object instanceof String) {
return StringUtils.stringToUnicode((String) object);
} else if (object instanceof List) {
ForEach.forEach((List<Object>) object, (t, i) -> {
((List<Object>) object).set(i, prossed(t));
});
}
return object;
}
public void decode(String path) {
try {
final Map<String, Object> map = jsonApi.parseFrom(
path,
new JsonTypeReference<HashMap<String, Object>>() {}
);
String s = jsonApi.format(prossed(map)).replace("\\\\u", "\\u");
FileUtil.writeStringToFile(StringUtils.format("old-{}", path), s);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,229 +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 OsPath.java
* LastUpdate 2025-09-14 22:12:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.path;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.*;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;
public class OsPath implements Path {
private final Path path;
private OsPath(Path path) {
this.path = path;
}
public static OsPath of(String path) {
return of(Paths.get(path));
}
public static OsPath of(Path path) {
return new OsPath(path);
}
public static OsPath of(URI uri) {
return new OsPath(Paths.get(uri));
}
public static OsPath of(File file) {
return new OsPath(file.toPath());
}
public static OsPath getCwd() {
return new OsPath(Paths.get(""));
}
@Override
public @NotNull FileSystem getFileSystem() {
return path.getFileSystem();
}
@Override
public boolean isAbsolute() {
return path.isAbsolute();
}
@Override
public Path getRoot() {
return path.getRoot();
}
@Override
public Path getFileName() {
return path.getFileName();
}
@Override
public Path getParent() {
Path a = path.getParent();
if (a == null) {
a = path.toAbsolutePath().getParent();
}
return a;
}
@Override
public int getNameCount() {
return path.getNameCount();
}
@Override
public @NotNull Path getName(int index) {
return path.getName(index);
}
@Override
public @NotNull Path subpath(int beginIndex, int endIndex) {
return path.subpath(beginIndex, endIndex);
}
@Override
public boolean startsWith(@NotNull Path other) {
return path.startsWith(other);
}
@Override
public boolean startsWith(@NotNull String other) {
return path.startsWith(other);
}
@Override
public boolean endsWith(@NotNull Path other) {
return path.endsWith(other);
}
@Override
public boolean endsWith(@NotNull String other) {
return path.endsWith(other);
}
@Override
public @NotNull Path normalize() {
return path.normalize();
}
@Override
public @NotNull Path resolve(@NotNull Path other) {
return path.resolve(other);
}
@Override
public @NotNull Path resolve(@NotNull String other) {
return path.resolve(other);
}
@Override
public @NotNull Path resolveSibling(@NotNull Path other) {
return path.resolveSibling(other);
}
@Override
public @NotNull Path resolveSibling(@NotNull String other) {
return path.resolveSibling(other);
}
@Override
public @NotNull Path relativize(@NotNull Path other) {
return path.relativize(other);
}
@Override
public @NotNull URI toUri() {
return path.toUri();
}
@Override
public @NotNull Path toAbsolutePath() {
return path.toAbsolutePath();
}
@Override
public @NotNull Path toRealPath(@NotNull LinkOption... options)
throws IOException {
return path.toRealPath(options);
}
@Override
public @NotNull File toFile() {
return path.toFile();
}
@Override
public @NotNull WatchKey register(
@NotNull WatchService watcher,
WatchEvent.@NotNull Kind<?>[] events,
@NotNull WatchEvent.Modifier... modifiers
) throws IOException {
return path.register(watcher, events, modifiers);
}
@Override
public @NotNull WatchKey register(
@NotNull WatchService watcher,
WatchEvent.@NotNull Kind<?>... events
) throws IOException {
return path.register(watcher, events);
}
@Override
public @NotNull Iterator<@NotNull Path> iterator() {
return path.iterator();
}
@Override
public int compareTo(@NotNull Path other) {
return path.compareTo(other);
}
@Override
public boolean equals(Object other) {
return path.equals(other);
}
@Override
public int hashCode() {
return path.hashCode();
}
@Override
public @NotNull String toString() {
return path.toString();
}
@Override
public void forEach(Consumer<? super Path> action) {
path.forEach(action);
}
@Override
public Spliterator<Path> spliterator() {
return path.spliterator();
}
}

View File

@ -1,25 +0,0 @@
package com.mingliqiye.utils.springboot.converters;
import static com.mingliqiye.utils.time.Formatter.STANDARD_DATETIME;
import com.mingliqiye.utils.time.DateTime;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* spring boot DateTime到字符串转换器
*
* @author MingliPro
* @see DateTime
*
*
*/
@Component
public class DateTimeToStringConverter implements Converter<DateTime, String> {
@Override
public String convert(@NotNull DateTime source) {
return source.format(STANDARD_DATETIME);
}
}

View File

@ -1,25 +0,0 @@
package com.mingliqiye.utils.springboot.converters;
import static com.mingliqiye.utils.time.Formatter.STANDARD_DATETIME_MILLISECOUND7;
import com.mingliqiye.utils.time.DateTime;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* spring boot 字符串到DateTime转换器
*
* @author MingliPro
* @see DateTime
*
*
*/
@Component
public class StringToDateTimeConverter implements Converter<String, DateTime> {
@Override
public DateTime convert(@NotNull String source) {
return DateTime.parse(source, STANDARD_DATETIME_MILLISECOUND7, true);
}
}

View File

@ -1,20 +0,0 @@
package com.mingliqiye.utils.springboot.converters;
import com.mingliqiye.utils.uuid.UUID;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* spring boot 字符串到UUID转换器
* @see UUID
* @author MingliPro
*/
@Component
public class StringToUUIDConverter implements Converter<String, UUID> {
@Override
public UUID convert(@NotNull String source) {
return UUID.of(source);
}
}

View File

@ -1,20 +0,0 @@
package com.mingliqiye.utils.springboot.converters;
import com.mingliqiye.utils.uuid.UUID;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* spring boot UUID到字符串转换器
* @see UUID
* @author MingliPro
*/
@Component
public class UUIDToStringConverter implements Converter<UUID, String> {
@Override
public String convert(@NotNull UUID source) {
return source.toUUIDString();
}
}

View File

@ -1,12 +1,36 @@
/*
* 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 InputStreamUtils.java
* LastUpdate 2025-09-15 08:30:57
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.stream; package com.mingliqiye.utils.stream;
import com.mingliqiye.utils.collection.Lists; import com.mingliqiye.utils.collection.Collections;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List; import java.util.List;
import lombok.val;
/** /**
* 输入流工具类提供对InputStream的常用操作封装 * 输入流工具类提供对InputStream的常用操作封装
@ -48,9 +72,9 @@ public class InputStreamUtils {
* @return 包含输入流所有数据的Byte列表 * @return 包含输入流所有数据的Byte列表
* @throws IOException 当读取输入流时发生IO异常 * @throws IOException 当读取输入流时发生IO异常
*/ */
public static List<Byte> readToList(InputStream inputStream) public static @NotNull List<Byte> readToList(InputStream inputStream)
throws IOException { throws IOException {
return Lists.toList(readToArray(inputStream)); return Collections.newArrayLists(readToArray(inputStream));
} }
/** /**

View File

@ -16,22 +16,20 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile SuperStream.java * CurrentFile SuperStream.java
* LastUpdate 2025-09-14 22:12:16 * LastUpdate 2025-09-15 09:30:37
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.stream; package com.mingliqiye.utils.stream;
import com.mingliqiye.utils.collection.Lists; import com.mingliqiye.utils.map.Maps;
import com.mingliqiye.utils.collection.Maps;
import com.mingliqiye.utils.stream.interfaces.Getable; import com.mingliqiye.utils.stream.interfaces.Getable;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.function.*; import java.util.function.*;
import java.util.stream.*; import java.util.stream.*;
import lombok.val;
import org.jetbrains.annotations.NotNull;
/** /**
* 自定义的 SuperStream 实现类用于对集合进行流式操作 * 自定义的 SuperStream 实现类用于对集合进行流式操作
@ -736,7 +734,7 @@ public class SuperStream<T> implements Stream<T> {
if (isEmpty()) { if (isEmpty()) {
return Optional.empty(); return Optional.empty();
} }
val l = Lists.toList(stream); val l = stream.collect(Collectors.toList());
return Optional.of(l.get(l.size() - 1)); return Optional.of(l.get(l.size() - 1));
} }

View File

@ -16,17 +16,16 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Main.kt * CurrentFile Main.kt
* LastUpdate 2025-09-14 22:05:03 * LastUpdate 2025-09-15 08:56:35
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("Main")
package com.mingliqiye.utils package com.mingliqiye.utils
import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration
fun main() { fun main() {
AutoConfiguration.printBanner() AutoConfiguration.printBanner()
} }
fun test() {
}

View File

@ -16,14 +16,13 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile ByteUtils.kt * CurrentFile ByteUtils.kt
* LastUpdate 2025-09-14 19:28:38 * LastUpdate 2025-09-15 00:07:22
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("ByteUtils") @file:JvmName("ByteUtils")
package com.mingliqiye.utils.bytes package com.mingliqiye.utils.bytes
import com.mingliqiye.utils.collection.Lists
import com.mingliqiye.utils.stream.SuperStream import com.mingliqiye.utils.stream.SuperStream
const val ESC_ASC: Byte = 0x10 const val ESC_ASC: Byte = 0x10
@ -42,7 +41,7 @@ const val ESC_RESERVED: Byte = 0x06
* @return 包含每个字节对应十六进制字符串的列表 * @return 包含每个字节对应十六进制字符串的列表
*/ */
fun ByteArray.getByteArrayString(): MutableList<String> { fun ByteArray.getByteArrayString(): MutableList<String> {
return Lists.toList(this)!!.stream() return this.toList().stream()
.map { a -> String.format("0X%02X", a!!.toInt() and 0xFF) } .map { a -> String.format("0X%02X", a!!.toInt() and 0xFF) }
.collect(SuperStream.Collectors.toList()) .collect(SuperStream.Collectors.toList())
} }

View File

@ -15,8 +15,8 @@
* *
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile CloneUtil.kt * CurrentFile CloneUtils.kt
* LastUpdate 2025-09-14 19:53:41 * LastUpdate 2025-09-15 09:30:37
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("CloneUtils") @file:JvmName("CloneUtils")

View File

@ -0,0 +1,470 @@
/*
* 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 Collection.kt
* LastUpdate 2025-09-15 09:30:37
* UpdateUser MingLiPro
*/
@file:JvmName("Collections")
package com.mingliqiye.utils.collection
import com.mingliqiye.utils.stream.SuperStream
import java.util.*
inline fun <reified T> Collection<T>.toArray(): Array<T> {
return arrayOf(*this.toTypedArray())
}
inline fun <reified T, V> Collection<T>.toMap(noinline v: (T) -> V): Map<T, V> {
return this.stream().collect(
SuperStream.Collectors.toMap(
SuperStream.Collectors::getThis, 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(
SuperStream.Collectors.toMap(
k, v
)
)
}
fun <T> toSet(array: Array<T>): Set<T> {
return array.toSet()
}
inline fun <reified T> Collection<T>.getFirst(): T? {
if (this.isEmpty()) {
return null
}
if (this is MutableList<T>) {
return this.first()
}
return this.iterator().next()
}
inline fun <reified T> Array<T>.getFirst(): T? {
if (this.isEmpty()) {
return null
}
return this.first()
}
inline fun <reified T> Collection<T>.getLast(): T? {
if (this.isEmpty()) {
return null
}
if (this is MutableList<T>) {
return this.last()
}
var lastElement: T? = null
for (element in this) {
lastElement = element
}
return lastElement
}
inline fun <reified T> Array<T>.getLast(): T? {
if (this.isEmpty()) {
return null
}
return this.last()
}
inline fun <reified T> Collection<T>.getOrDefault(
index: Int, defaultValue: T
): T {
if (!(!this.isEmpty() && index < this.size)) {
return defaultValue
}
if (this is List<T>) {
return this[index]
}
var i = 0
for (element in this) {
if (i == index) {
return element
}
i++
}
return defaultValue
}
fun <T> newArrayList(): ArrayList<T> {
return ArrayList()
}
fun <T> newArrayList(size: Int): ArrayList<T> {
return ArrayList()
}
fun <T> newArrayList(vararg elements: T): ArrayList<T> {
return newArrayList(elements.asList())
}
fun <T> Collection<T>.newArrayLists(): ArrayList<T> {
return newArrayList(this)
}
fun <T> newArrayLists(elements: Array<T>): ArrayList<T> {
return newArrayList(elements.asList())
}
fun <T> newArrayList(elements: Collection<T>): ArrayList<T> {
return ArrayList(elements.toList())
}
fun <T> newArrayList(elements: Iterable<T>): ArrayList<T> {
return newArrayList(elements.toList())
}
fun <T> newArrayList(elements: Sequence<T>): ArrayList<T> {
return newArrayList(elements.toList())
}
fun <T> newLinkedList(): LinkedList<T> {
return LinkedList()
}
fun <T> newLinkedList(vararg elements: T): LinkedList<T> {
val list = newLinkedList<T>()
list.addAll(elements.asList())
return list
}
fun <T> newLinkedList(elements: Collection<T>): LinkedList<T> {
val list = newLinkedList<T>()
list.addAll(elements)
return list
}
fun <T> newLinkedList(elements: Iterable<T>): LinkedList<T> {
val list = newLinkedList<T>()
for (element in elements) {
list.add(element)
}
return list
}
fun <T> newLinkedList(elements: Sequence<T>): LinkedList<T> {
return newLinkedList(elements.toList())
}
fun <T> newVector(): Vector<T> {
return Vector()
}
fun <T> newVector(vararg elements: T): Vector<T> {
val vector = newVector<T>()
vector.addAll(elements.asList())
return vector
}
fun <T> newVector(elements: Collection<T>): Vector<T> {
val vector = newVector<T>()
vector.addAll(elements)
return vector
}
fun <T> newVector(elements: Iterable<T>): Vector<T> {
val vector = newVector<T>()
for (element in elements) {
vector.add(element)
}
return vector
}
fun <T> newVector(elements: Sequence<T>): Vector<T> {
return newVector(elements.toList())
}
fun <T> newHashSet(): HashSet<T> {
return HashSet()
}
fun <T> newHashSet(size: Int): HashSet<T> {
return HashSet(size)
}
fun <T> newHashSet(vararg elements: T): HashSet<T> {
val set = newHashSet<T>()
set.addAll(elements.asList())
return set
}
fun <T> newHashSet(elements: Collection<T>): HashSet<T> {
val set = newHashSet<T>()
set.addAll(elements)
return set
}
fun <T> newHashSet(elements: Iterable<T>): HashSet<T> {
val set = newHashSet<T>()
for (element in elements) {
set.add(element)
}
return set
}
fun <T> newHashSet(elements: Sequence<T>): HashSet<T> {
return newHashSet(elements.toSet())
}
fun <T> newLinkedHashSet(): LinkedHashSet<T> {
return LinkedHashSet()
}
fun <T> newLinkedHashSet(size: Int): LinkedHashSet<T> {
return LinkedHashSet(size)
}
fun <T> newLinkedHashSet(vararg elements: T): LinkedHashSet<T> {
val set = newLinkedHashSet<T>()
set.addAll(elements.asList())
return set
}
fun <T> newLinkedHashSet(elements: Collection<T>): LinkedHashSet<T> {
val set = newLinkedHashSet<T>()
set.addAll(elements)
return set
}
fun <T> newLinkedHashSet(elements: Iterable<T>): LinkedHashSet<T> {
val set = newLinkedHashSet<T>()
for (element in elements) {
set.add(element)
}
return set
}
fun <T> newLinkedHashSet(elements: Sequence<T>): LinkedHashSet<T> {
return newLinkedHashSet(elements.toSet())
}
fun <T : Comparable<T>> newTreeSet(): TreeSet<T> {
return TreeSet()
}
fun <T : Comparable<T>> newTreeSet(vararg elements: T): TreeSet<T> {
val set = newTreeSet<T>()
set.addAll(elements.asList())
return set
}
fun <T : Comparable<T>> newTreeSet(elements: Collection<T>): TreeSet<T> {
val set = newTreeSet<T>()
set.addAll(elements)
return set
}
fun <T : Comparable<T>> newTreeSet(elements: Iterable<T>): TreeSet<T> {
val set = newTreeSet<T>()
for (element in elements) {
set.add(element)
}
return set
}
fun <T : Comparable<T>> newTreeSet(elements: Sequence<T>): TreeSet<T> {
return newTreeSet(elements.toSet())
}
fun newArrayLists(elements: ByteArray): ArrayList<Byte> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: ShortArray): ArrayList<Short> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: IntArray): ArrayList<Int> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: LongArray): ArrayList<Long> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: FloatArray): ArrayList<Float> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: DoubleArray): ArrayList<Double> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: BooleanArray): ArrayList<Boolean> {
return ArrayList(elements.toList())
}
fun newArrayLists(elements: CharArray): ArrayList<Char> {
return ArrayList(elements.toList())
}
fun <T> newCopyOnWriteArrayList(): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList()
}
fun <T> newCopyOnWriteArrayList(vararg elements: T): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList(elements.asList())
}
fun <T> newCopyOnWriteArrayList(elements: Collection<T>): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList(elements)
}
fun <T> newStack(): Stack<T> {
return Stack()
}
fun <T> newStack(vararg elements: T): Stack<T> {
val stack = newStack<T>()
stack.addAll(elements.asList())
return stack
}
fun <T> newStack(elements: Collection<T>): Stack<T> {
val stack = newStack<T>()
stack.addAll(elements)
return stack
}
fun <T> newTreeSet(comparator: Comparator<T>): TreeSet<T> {
return TreeSet(comparator)
}
fun <T> newTreeSet(comparator: Comparator<T>, vararg elements: T): TreeSet<T> {
val set = newTreeSet(comparator)
set.addAll(elements.asList())
return set
}
fun <T> newTreeSet(comparator: Comparator<T>, elements: Collection<T>): TreeSet<T> {
val set = newTreeSet(comparator)
set.addAll(elements)
return set
}
fun <T> newTreeSet(comparator: Comparator<T>, elements: Iterable<T>): TreeSet<T> {
val set = newTreeSet(comparator)
for (element in elements) {
set.add(element)
}
return set
}
fun <T> newTreeSet(comparator: Comparator<T>, elements: Sequence<T>): TreeSet<T> {
return newTreeSet(comparator, elements.toSet())
}
fun <T> Collection<T>.newCopyOnWriteArrayLists(): java.util.concurrent.CopyOnWriteArrayList<T> {
return java.util.concurrent.CopyOnWriteArrayList(this)
}
fun <T> Collection<T>.newStacks(): Stack<T> {
val stack = Stack<T>()
stack.addAll(this)
return stack
}
fun <T> Collection<T>.newTreeSets(): TreeSet<T> where T : Comparable<T> {
val set = TreeSet<T>()
set.addAll(this)
return set
}
fun <T> Collection<T>.newTreeSets(comparator: Comparator<T>): TreeSet<T> {
val set = TreeSet(comparator)
set.addAll(this)
return set
}
fun toArray(list: List<Byte>): ByteArray {
val arr = ByteArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Short>): ShortArray {
val arr = ShortArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Int>): IntArray {
val arr = IntArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Long>): LongArray {
val arr = LongArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Float>): FloatArray {
val arr = FloatArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Double>): DoubleArray {
val arr = DoubleArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Boolean>): BooleanArray {
val arr = BooleanArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}
fun toArray(list: List<Char>): CharArray {
val arr = CharArray(list.size)
for (i in list.indices) {
arr[i] = list[i]
}
return arr
}

View File

@ -0,0 +1,104 @@
/*
* 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 IsChanged.kt
* LastUpdate 2025-09-15 09:30:37
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.concurrent
import java.util.*
import java.util.concurrent.atomic.AtomicReference
/**
* IsChanged 类提供了一个线程安全的包装器用于检测值是否发生变化
* 它基于 AtomicReference 实现适用于需要监控数据变更的并发场景
*
* @param T 泛型类型表示被包装的数据类型
* @author MingLiPro
*/
class IsChanged<T> {
/**
* 使用 AtomicReference 来保证对数据的原子操作
*/
private val atomicReferenceData: AtomicReference<T> = AtomicReference()
/**
* 默认构造函数初始化数据为 null
*/
constructor() : this(null)
/**
* 带参数的构造函数使用指定的初始值初始化
*
* @param data 初始数据值
*/
constructor(data: T?) : super() {
atomicReferenceData.set(data)
}
/**
* 设置新的数据值不检查是否发生变化
*
* @param data 要设置的新数据值
*/
fun set(data: T) {
atomicReferenceData.set(data)
}
/**
* 获取当前数据值
*
* @return 当前数据值
*/
fun get(): T? {
return atomicReferenceData.get()
}
/**
* 设置新的数据值并返回旧的数据值
*
* @param data 要设置的新数据值
* @return 设置前的旧数据值
*/
fun setAndGet(data: T): T? {
return atomicReferenceData.getAndSet(data)
}
/**
* 设置新的数据值如果新值与当前值不同则更新并返回 true否则返回 false
* 使用 CAS(Compare-And-Swap) 操作确保线程安全
*
* @param data 要设置的新数据值
* @return 如果值发生变化返回 true否则返回 false
*/
fun setAndChanged(data: T): Boolean {
var currentData: T?
do {
currentData = get()
// 如果新值与当前值相等,则认为没有变化,直接返回 false
if (Objects.equals(data, currentData)) {
return false
}
// 使用 CAS 操作尝试更新值,如果失败则重试
} while (!atomicReferenceData.compareAndSet(currentData, data))
// 成功更新值,返回 true 表示发生了变化
return true
}
}

View File

@ -0,0 +1,98 @@
/*
* 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 ThreadLocalDataHolder.kt
* LastUpdate 2025-09-15 09:15:14
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.data
/**
* 泛型线程局部变量持有器
*
* 封装了 ThreadLocal 的常用操作提供更便捷的 API 来管理线程本地变量
*
* @param T 存储的数据类型
* @author MingLiPro
*/
class ThreadLocalDataHolder<T> {
private val threadLocal: ThreadLocal<T?> = ThreadLocal()
/**
* 获取当前线程存储的值
*
* @return 当前线程存储的值如果没有则返回null
*/
fun get(): T? {
return threadLocal.get()
}
/**
* 设置当前线程的值
*
* @param value 要存储的值
*/
fun set(value: T) {
threadLocal.set(value)
}
/**
* 移除当前线程存储的值
*
* 防止内存泄漏使用完毕后应调用此方法清理资源
*/
fun remove() {
threadLocal.remove()
}
/**
* 获取当前线程存储的值如果不存在则返回默认值
*
* @param defaultValue 默认值
* @return 当前线程存储的值或默认值
*/
fun getOrDefault(defaultValue: T): T {
val value = threadLocal.get()
return value ?: defaultValue
}
/**
* 安全获取值避免NPE
*
* 在某些异常情况下防止抛出异常直接返回 null
*
* @return 值或null
*/
fun safeGet(): T? {
return try {
threadLocal.get()
} catch (e: Exception) {
null
}
}
/**
* 检查当前线程是否有值
*
* @return 是否有值
*/
fun isPresent(): Boolean {
return threadLocal.get() != null
}
}

View File

@ -0,0 +1,346 @@
/*
* 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 FileUtils.kt
* LastUpdate 2025-09-15 09:12:47
* UpdateUser MingLiPro
*/
@file:JvmName("FileUtils")
package com.mingliqiye.utils.file
import com.mingliqiye.utils.path.OsPath
import java.io.IOException
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
/**
* 默认字符集
*/
var DEFAULT_CHARSET: Charset = StandardCharsets.UTF_8
/**
* 读取文件内容为字符串
*
* @param filePath 文件路径
* @return 文件内容字符串
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readFileToString(filePath: String): String {
return readFileToString(filePath, DEFAULT_CHARSET)
}
/**
* 读取文件内容为字符串
*
* @param filePath 文件路径
* @param charset 字符集
* @return 文件内容字符串
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readFileToString(filePath: String, charset: Charset): String {
val path = OsPath.of(filePath)
val bytes = Files.readAllBytes(path)
return String(bytes, charset)
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 要写入的内容
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeStringToFile(filePath: String, content: String) {
writeStringToFile(filePath, content, DEFAULT_CHARSET)
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 要写入的内容
* @param charset 字符集
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeStringToFile(filePath: String, content: String, charset: Charset) {
val path = Paths.get(filePath)
path.parent?.let { Files.createDirectories(it) }
Files.write(path, content.toByteArray(charset))
}
/**
* 读取文件内容为字符串列表按行分割
*
* @param filePath 文件路径
* @return 文件内容按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readLines(filePath: String): List<String> {
return readLines(filePath, DEFAULT_CHARSET)
}
/**
* 读取文件内容为字符串列表按行分割
*
* @param filePath 文件路径
* @param charset 字符集
* @return 文件内容按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readLines(filePath: String, charset: Charset): List<String> {
val path = Paths.get(filePath)
return Files.readAllLines(path, charset)
}
/**
* 将字符串列表写入文件每行一个元素
*
* @param filePath 文件路径
* @param lines 要写入的行内容列表
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeLines(filePath: String, lines: List<String>) {
writeLines(filePath, lines, DEFAULT_CHARSET)
}
/**
* 将字符串列表写入文件每行一个元素
*
* @param filePath 文件路径
* @param lines 要写入的行内容列表
* @param charset 字符集
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeLines(filePath: String, lines: List<String>, charset: Charset) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent)
Files.write(path, lines, charset)
}
/**
* 复制文件
*
* @param sourcePath 源文件路径
* @param targetPath 目标文件路径
* @throws IOException 复制文件时发生错误
*/
@Throws(IOException::class)
fun copyFile(sourcePath: String, targetPath: String) {
val source = Paths.get(sourcePath)
val target = Paths.get(targetPath)
Files.createDirectories(target.parent)
Files.copy(source, target)
}
/**
* 删除文件
*
* @param filePath 文件路径
* @return 如果文件删除成功返回true否则返回false
*/
fun deleteFile(filePath: String): Boolean {
return try {
val path = Paths.get(filePath)
Files.deleteIfExists(path)
} catch (e: IOException) {
false
}
}
/**
* 检查文件是否存在
*
* @param filePath 文件路径
* @return 如果文件存在返回true否则返回false
*/
fun exists(filePath: String): Boolean {
val path = Paths.get(filePath)
return Files.exists(path)
}
/**
* 获取文件大小
*
* @param filePath 文件路径
* @return 文件大小字节如果文件不存在返回-1
*/
fun getFileSize(filePath: String): Long {
return try {
val path = Paths.get(filePath)
Files.size(path)
} catch (e: IOException) {
-1
}
}
/**
* 创建目录
*
* @param dirPath 目录路径
* @return 如果目录创建成功返回true否则返回false
*/
fun createDirectory(dirPath: String): Boolean {
return try {
val path = Paths.get(dirPath)
Files.createDirectories(path)
true
} catch (e: IOException) {
false
}
}
/**
* 获取文件扩展名
*
* @param fileName 文件名
* @return 文件扩展名不包含点号如果无扩展名返回空字符串
*/
fun getFileExtension(fileName: String): String {
if (fileName.isEmpty()) {
return ""
}
val lastDotIndex = fileName!!.lastIndexOf('.')
return if (lastDotIndex == -1 || lastDotIndex == fileName.length - 1) {
""
} else fileName.substring(lastDotIndex + 1)
}
/**
* 获取不带扩展名的文件名
*
* @param fileName 文件名
* @return 不带扩展名的文件名
*/
fun getFileNameWithoutExtension(fileName: String): String {
if (fileName.isEmpty()) {
return ""
}
val lastDotIndex = fileName!!.lastIndexOf('.')
return if (lastDotIndex == -1) {
fileName
} else fileName.substring(0, lastDotIndex)
}
/**
* 读取文件内容为字节数组
*
* @param filePath 文件路径
* @return 文件内容的字节数组
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readFileToByteArray(filePath: String): ByteArray {
val path = Paths.get(filePath)
return Files.readAllBytes(path)
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param data 要写入的字节数据
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeByteArrayToFile(filePath: String, data: ByteArray) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent)
Files.write(path, data)
}
/**
* 将字节数组追加到文件末尾
*
* @param filePath 文件路径
* @param data 要追加的字节数据
* @throws IOException 追加数据时发生错误
*/
@Throws(IOException::class)
fun appendByteArrayToFile(filePath: String, data: ByteArray) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent)
Files.write(
path, data, StandardOpenOption.CREATE, StandardOpenOption.APPEND
)
}
/**
* 分块读取大文件为字节数组列表
*
* @param filePath 文件路径
* @param chunkSize 每块大小字节
* @return 文件内容按指定大小分割的字节数组列表
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readFileToByteArrayChunks(filePath: String, chunkSize: Int): List<ByteArray> {
val chunks = mutableListOf<ByteArray>()
val path = Paths.get(filePath)
Files.newInputStream(path).use { inputStream ->
val buffer = ByteArray(chunkSize)
var bytesRead: Int
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
val chunk = ByteArray(bytesRead)
System.arraycopy(buffer, 0, chunk, 0, bytesRead)
chunks.add(chunk)
}
}
return chunks
}
/**
* 将字节数组列表写入文件
*
* @param filePath 文件路径
* @param chunks 字节数组列表
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeByteArrayChunksToFile(filePath: String, chunks: List<ByteArray>) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent)
Files.newOutputStream(path).use { outputStream ->
for (chunk in chunks) {
outputStream.write(chunk)
}
}
}

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 Response.kt
* LastUpdate 2025-09-15 09:04:05
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.http
import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.Formatter
data class Response<T>(
val time: String,
var message: String,
var data: T?,
var statusCode: Int
) {
companion object {
@JvmStatic
fun <T> ok(data: T): Response<T?> {
return Response(DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7), "操作成功", data, 200)
}
@JvmStatic
fun <T> ok(message: String): Response<T?> {
return Response(DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7), message, null, 200)
}
}
fun setMessage(message: String): Response<T> {
this.message = message
return this
}
fun setData(data: T): Response<T?> {
this.data = data
return ok(this.data)
.setMessage(this.message)
.setStatusCode(this.statusCode)
}
fun setStatusCode(statusCode: Int): Response<T> {
this.statusCode = statusCode
return this
}
}

View File

@ -0,0 +1,167 @@
/*
* 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 Maps.kt
* LastUpdate 2025-09-15 08:33:24
* UpdateUser MingLiPro
*/
@file:JvmName("Maps")
package com.mingliqiye.utils.map
import java.util.*
import java.util.concurrent.ConcurrentHashMap
fun <K, V> newHashMap(vararg elements: Pair<K, V>): HashMap<K, V> {
val map = HashMap<K, V>()
for (element in elements) {
map[element.first] = element.second
}
return map
}
fun <K, V> newHashMap(size: Int): HashMap<K, V> {
return HashMap(size)
}
fun <K, V> newHashMap(vararg elements: Map.Entry<K, V>): HashMap<K, V> {
val map = HashMap<K, V>()
for (element in elements) {
map[element.key] = element.value
}
return map
}
fun <K, V> newConcurrentHashMap(vararg elements: Map.Entry<K, V>): ConcurrentHashMap<K, V> {
val map = newConcurrentHashMap<K, V>()
for (element in elements) {
map[element.key] = element.value
}
return map
}
fun <K, V> newLinkedHashMap(vararg elements: Map.Entry<K, V>): LinkedHashMap<K, V> {
val map = newLinkedHashMap<K, V>()
for (element in elements) {
map[element.key] = element.value
}
return map
}
fun <K, V> newHashtable(vararg elements: Map.Entry<K, V>): Hashtable<K, V> {
val map = newHashtable<K, V>()
for (element in elements) {
map[element.key] = element.value
}
return map
}
fun <K : Comparable<K>, V> newTreeMap(vararg elements: Map.Entry<K, V>): TreeMap<K, V> {
val map = newTreeMap<K, V>()
for (element in elements) {
map[element.key] = element.value
}
return map
}
inline fun <reified K, reified V> Map<K, V>.newHashMap(): HashMap<K, V> {
return HashMap(this)
}
fun <K, V> newLinkedHashMap(): LinkedHashMap<K, V> {
return LinkedHashMap()
}
fun <K, V> newLinkedHashMap(size: Int): LinkedHashMap<K, V> {
return LinkedHashMap(size)
}
fun <K, V> newLinkedHashMap(vararg elements: Pair<K, V>): LinkedHashMap<K, V> {
val map = newLinkedHashMap<K, V>()
for (element in elements) {
map[element.first] = element.second
}
return map
}
inline fun <reified K, reified V> Map<K, V>.newLinkedHashMap(): LinkedHashMap<K, V> {
return LinkedHashMap(this)
}
fun <K : Comparable<K>, V> newTreeMap(): TreeMap<K, V> {
return TreeMap()
}
fun <K : Comparable<K>, V> newTreeMap(vararg elements: Pair<K, V>): TreeMap<K, V> {
val map = newTreeMap<K, V>()
for (element in elements) {
map[element.first] = element.second
}
return map
}
inline fun <reified K : Comparable<K>, reified V> Map<K, V>.newTreeMap(): TreeMap<K, V> {
return TreeMap(this)
}
fun <K, V> newHashtable(): Hashtable<K, V> {
return Hashtable()
}
fun <K, V> newHashtable(size: Int): Hashtable<K, V> {
return Hashtable(size)
}
fun <K, V> newHashtable(vararg elements: Pair<K, V>): Hashtable<K, V> {
val map = newHashtable<K, V>()
for (element in elements) {
map[element.first] = element.second
}
return map
}
inline fun <reified K, reified V> Map<K, V>.newHashtable(): Hashtable<K, V> {
val hashtable = Hashtable<K, V>()
hashtable.putAll(this)
return hashtable
}
fun <K, V> newConcurrentHashMap(): ConcurrentHashMap<K, V> {
return ConcurrentHashMap()
}
fun <K, V> newConcurrentHashMap(size: Int): ConcurrentHashMap<K, V> {
return ConcurrentHashMap(size)
}
fun <K, V> newConcurrentHashMap(vararg elements: Pair<K, V>): ConcurrentHashMap<K, V> {
val map = newConcurrentHashMap<K, V>()
for (element in elements) {
map[element.first] = element.second
}
return map
}
inline fun <reified K, reified V> Map<K, V>.newConcurrentHashMap(): ConcurrentHashMap<K, V> {
return ConcurrentHashMap(this)
}
fun <K, V> ofEntries(entries: List<MutableMap.MutableEntry<K, V>>): Map<K, V> {
return entries.associate { it.key to it.value }
}

View File

@ -0,0 +1,105 @@
/*
* 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 OsPath.kt
* LastUpdate 2025-09-15 08:59:15
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.path
import java.io.File
import java.net.URI
import java.nio.file.*
import java.util.*
import java.util.function.Consumer
class OsPath private constructor(private val path: Path) : Path by path {
companion object {
@JvmStatic
fun of(path: String): OsPath {
return of(Paths.get(path))
}
@JvmStatic
fun of(path: Path): OsPath {
return OsPath(path)
}
@JvmStatic
fun of(uri: URI): OsPath {
return OsPath(Paths.get(uri))
}
@JvmStatic
fun of(file: File): OsPath {
return OsPath(file.toPath())
}
@JvmStatic
fun getCwd(): OsPath {
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

@ -16,14 +16,13 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile RandomBytes.kt * CurrentFile RandomBytes.kt
* LastUpdate 2025-09-12 17:11:19 * LastUpdate 2025-09-15 00:08:18
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("RandomBytes") @file:JvmName("RandomBytes")
package com.mingliqiye.utils.random package com.mingliqiye.utils.random
import com.mingliqiye.utils.collection.ForEach
import com.mingliqiye.utils.iterator.Range import com.mingliqiye.utils.iterator.Range
/** /**
@ -33,9 +32,7 @@ import com.mingliqiye.utils.iterator.Range
*/ */
fun randomBytes(length: Int): ByteArray { fun randomBytes(length: Int): ByteArray {
val bytes = ByteArray(length) val bytes = ByteArray(length)
ForEach.forEach( Range(0, length - 1).forEach { i: Int -> bytes[i] = randomByte(0x00.toByte(), 0xff.toByte()) }
Range(0, length - 1)
) { i: Int -> bytes[i] = randomByte(0x00.toByte(), 0xff.toByte()) }
return bytes return bytes
} }

View File

@ -16,13 +16,12 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile AutoConfiguration.kt * CurrentFile AutoConfiguration.kt
* LastUpdate 2025-09-14 22:09:46 * LastUpdate 2025-09-15 08:51:52
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.springboot.autoconfigure package com.mingliqiye.utils.springboot.autoconfigure
import com.mingliqiye.utils.collection.ForEach
import com.mingliqiye.utils.logger.mingLiLoggerFactory import com.mingliqiye.utils.logger.mingLiLoggerFactory
import com.mingliqiye.utils.system.getJdkVersion import com.mingliqiye.utils.system.getJdkVersion
import com.mingliqiye.utils.time.DateTime import com.mingliqiye.utils.time.DateTime
@ -47,8 +46,6 @@ open class AutoConfiguration {
"| $$ |\\$ /$$ |$$ | $$ | $$ | $$ | $$\\ $$ | |\n" + "| $$ |\\$ /$$ |$$ | $$ | $$ | $$ | $$\\ $$ | |\n" +
"| $$ | \\_/ $$ |$$$$$$$$\\\\$$$$$$ | $$ | \\$$$$$$ | |\n" + "| $$ | \\_/ $$ |$$$$$$$$\\\\$$$$$$ | $$ | \\$$$$$$ | |\n" +
"| \\__| \\__|\\________|\\______/ \\__| \\______/ |\n" "| \\__| \\__|\\________|\\______/ \\__| \\______/ |\n"
private var banner2: String? = null
private val log = mingLiLoggerFactory.getLogger("MingliUtils-AutoConfiguration") private val log = mingLiLoggerFactory.getLogger("MingliUtils-AutoConfiguration")
fun printBanner() { fun printBanner() {
@ -68,7 +65,7 @@ open class AutoConfiguration {
val da = metaData.toString().split("\n").toMutableList() val da = metaData.toString().split("\n").toMutableList()
da.add("time=" + DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7)) da.add("time=" + DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7))
da.add("jdkRuntime=" + getJdkVersion()) da.add("jdkRuntime=" + getJdkVersion())
ForEach.forEach(da) { s: String, _: Int -> da.forEach { s: String ->
val d = s.trim { it <= ' ' }.split("=".toRegex(), 2).toTypedArray() val d = s.trim { it <= ' ' }.split("=".toRegex(), 2).toTypedArray()
if (d.size >= 2) { if (d.size >= 2) {
val content = "| " + d[0] + ": " + d[1] val content = "| " + d[0] + ": " + d[1]
@ -91,8 +88,7 @@ open class AutoConfiguration {
} catch (e: IOException) { } catch (e: IOException) {
e.printStackTrace() e.printStackTrace()
} }
banner2 = bannerBuilder.toString() println(bannerBuilder.toString().trim())
println(banner2)
println("---------------------------------------------------------") println("---------------------------------------------------------")
} }
} }

View File

@ -0,0 +1,58 @@
/*
* 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 Converters.kt
* LastUpdate 2025-09-15 09:19:48
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.springboot.converters
import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.Formatter
import com.mingliqiye.utils.uuid.UUID
import com.mingliqiye.utils.uuid.UUID.Companion.of
import org.springframework.core.convert.converter.Converter
import org.springframework.stereotype.Component
@Component
class DateTimeToStringConverter : Converter<DateTime, String?> {
override fun convert(source: DateTime): String {
return source.format(Formatter.STANDARD_DATETIME)
}
}
@Component
class UUIDToStringConverter : Converter<UUID, String> {
override fun convert(source: UUID): String {
return source.getString()
}
}
@Component
class StringToDateTimeConverter : Converter<String, DateTime> {
override fun convert(source: String): DateTime {
return DateTime.parse(source, Formatter.STANDARD_DATETIME_MILLISECOUND7, true)
}
}
@Component
class StringToUUIDConverter : Converter<String, UUID> {
override fun convert(source: String): UUID {
return of(source)
}
}

View File

@ -16,14 +16,13 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile SystemUtil.kt * CurrentFile SystemUtil.kt
* LastUpdate 2025-09-14 21:56:58 * LastUpdate 2025-09-15 08:50:23
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("SystemUtils") @file:JvmName("SystemUtils")
package com.mingliqiye.utils.system package com.mingliqiye.utils.system
import com.mingliqiye.utils.collection.Lists
import java.net.Inet4Address import java.net.Inet4Address
import java.net.NetworkInterface import java.net.NetworkInterface
import java.net.SocketException import java.net.SocketException
@ -90,14 +89,14 @@ fun getJavaVersionAsInteger(): Int {
"Invalid Java version format: $version" "Invalid Java version format: $version"
) )
} }
version.substring(2, 3) version[2] + ""
} else { } else {
if (version.length < 2) { if (version.length < 2) {
throw IllegalStateException( throw IllegalStateException(
"Invalid Java version format: $version" "Invalid Java version format: $version"
) )
} }
version.substring(0, 2) version.take(2)
} }
return uversion.toInt() return uversion.toInt()
} }
@ -151,7 +150,7 @@ fun getLocalIps(): Array<String> {
* @return 本地IP地址的字符串列表 * @return 本地IP地址的字符串列表
*/ */
fun getLocalIpsByList(): List<String> { fun getLocalIpsByList(): List<String> {
return Lists.newArrayList(*getLocalIps()) return getLocalIps().toList()
} }
/** /**
@ -179,7 +178,6 @@ fun getLoopbackIps(): Array<String> {
} }
strings.toTypedArray() strings.toTypedArray()
} catch (e: SocketException) { } catch (e: SocketException) {
// 可考虑添加日志记录
arrayOf("127.0.0.1") arrayOf("127.0.0.1")
} }
} }
@ -191,5 +189,5 @@ fun getLoopbackIps(): Array<String> {
*/ */
fun getLoopbackIpsByList(): List<String> { fun getLoopbackIpsByList(): List<String> {
// 将本地回环地址IP数组转换为列表并返回 // 将本地回环地址IP数组转换为列表并返回
return Lists.newArrayList(*getLoopbackIps()) return getLoopbackIps().toList()
} }

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile UUID.kt * CurrentFile UUID.kt
* LastUpdate 2025-09-14 19:55:47 * LastUpdate 2025-09-14 22:38:51
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.uuid package com.mingliqiye.utils.uuid
@ -44,6 +44,9 @@ class UUID : Serializable {
return UUID(UuidCreator.getTimeBased()) return UUID(UuidCreator.getTimeBased())
} }
@Deprecated("使用 getV1()", ReplaceWith("getV1()"), level = DeprecationLevel.WARNING)
fun getTimeBased(): UUID = getV1()
/** /**
* 获取 UUIDV4 版本的随机实例 * 获取 UUIDV4 版本的随机实例
* @return UUID * @return UUID