generated from mingliqiye/lib-tem
refactor(mingli-utils):重构集合工具类并添加新功能
- 重写 Collection 类,使用 Kotlin 语法和特性优化代码结构 - 添加新方法以支持数组和集合之间的转换 - 新增 CopyOnWriteArrayList、Stack 和 TreeSet 相关方法 -优化现有方法,提高代码可读性和性能 - 删除未使用的 ForEach 导入 -调整 build.gradle.kts 中的依赖项
This commit is contained in:
parent
d6a2117b58
commit
dc129c016f
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
30
src/main/java/com/mingliqiye/utils/Main.java
Normal file
30
src/main/java/com/mingliqiye/utils/Main.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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() {
|
||||||
|
}
|
||||||
|
|||||||
@ -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())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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")
|
||||||
470
src/main/kotlin/com/mingliqiye/utils/collection/Collection.kt
Normal file
470
src/main/kotlin/com/mingliqiye/utils/collection/Collection.kt
Normal 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
|
||||||
|
}
|
||||||
104
src/main/kotlin/com/mingliqiye/utils/concurrent/IsChanged.kt
Normal file
104
src/main/kotlin/com/mingliqiye/utils/concurrent/IsChanged.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
346
src/main/kotlin/com/mingliqiye/utils/file/FileUtils.kt
Normal file
346
src/main/kotlin/com/mingliqiye/utils/file/FileUtils.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/main/kotlin/com/mingliqiye/utils/http/Response.kt
Normal file
63
src/main/kotlin/com/mingliqiye/utils/http/Response.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
167
src/main/kotlin/com/mingliqiye/utils/map/Maps.kt
Normal file
167
src/main/kotlin/com/mingliqiye/utils/map/Maps.kt
Normal 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 }
|
||||||
|
}
|
||||||
105
src/main/kotlin/com/mingliqiye/utils/path/OsPath.kt
Normal file
105
src/main/kotlin/com/mingliqiye/utils/path/OsPath.kt
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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("---------------------------------------------------------")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user