feat(utils): 添加高精度时间获取功能并优化相关工具类
All checks were successful
Gitea Actions Build / Build (push) Successful in 54s

- 新增 AutoConfiguration 类,用于 Spring Boot 自动配置
- 添加高精度时间获取功能,兼容 Java1.8 及以上版本- 优化 DateTime 类,增加 fileTimeToLocalDateTime 方法
- 更新 ForEach 类,增加对基本类型数组的遍历支持
-调整 Factory 类,使用 BEANS 和 TYPE_BEANS 替代原变量名
- 更新 ByteUtil 类,添加常用字节常量- 修改 HashUtils 类,优化文件读取缓冲区大小
This commit is contained in:
Armamem0t 2025-09-02 16:15:35 +08:00
parent cb10406455
commit 9ebd09a810
Signed by: minglipro
GPG Key ID: 5F355A77B22AA93B
22 changed files with 2189 additions and 46 deletions

View File

@ -1,3 +1,6 @@
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
plugins {
idea
id("java-library")
@ -22,18 +25,17 @@ java {
}
dependencies {
annotationProcessor("org.jetbrains:annotations:24.0.0")
annotationProcessor("org.projectlombok:lombok:1.18.38")
compileOnly("org.springframework.boot:spring-boot-starter:2.7.14")
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2")
compileOnly("org.mybatis:mybatis:3.5.19")
compileOnly("org.projectlombok:lombok:1.18.38")
implementation("org.bouncycastle:bcprov-jdk18on:1.81")
implementation("com.github.f4b6a3:uuid-creator:6.1.0")
implementation("org.mindrot:jbcrypt:0.4")
implementation("org.jetbrains:annotations:24.0.0")
compileOnly("org.projectlombok:lombok:1.18.38")
annotationProcessor("org.jetbrains:annotations:24.0.0")
annotationProcessor("org.projectlombok:lombok:1.18.38")
implementation("net.java.dev.jna:jna:5.17.0")
}
@ -59,6 +61,22 @@ tasks.withType<Javadoc> {
options.encoding = "UTF-8"
}
tasks.withType<org.gradle.jvm.tasks.Jar> {
manifest {
attributes(
mapOf(
"Implementation-Title" to ARTIFACTID,
"Implementation-Version" to VERSIONS,
"Implementation-Package" to GROUPSID,
"Implementation-Vendor" to "minglipro",
"Implementation-Build-Time" to LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
)
)
}
}
repositories {
mavenCentral()
}
@ -79,3 +97,19 @@ publishing {
}
}
}
tasks.processResources {
filesMatching("META-INF/meta-data") {
expand(
mapOf(
"buildTime" to LocalDateTime.now()
.format(
DateTimeFormatter.ofPattern(
"yyyy-MM-dd HH:mm:ss.SSSSSSS"
)
)
) + project.properties
)
}
}

View File

@ -1,4 +1,4 @@
JDKVERSIONS=1.8
GROUPSID=com.mingliqiye.utils
ARTIFACTID=mingli-utils
VERSIONS=1.1.4
VERSIONS=2.0.0

View File

@ -0,0 +1,7 @@
buildTime=$buildTime
groupId=$GROUPSID
artifactId=$ARTIFACTID
version=$VERSIONS
buildJdkVersion=$JDKVERSIONS
author=MingLiPro
website=mingliqiye.com

View File

@ -0,0 +1 @@
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration

View File

@ -19,13 +19,13 @@ public class Factory {
/**
* 存储所有已注册的Bean实例键为Bean名称值为Bean实例
*/
public static final ConcurrentMap<String, Object> beans =
public static final ConcurrentMap<String, Object> BEANS =
new ConcurrentHashMap<>();
/**
* 存储按类型查找的Bean实例键为Bean的Class对象值为Bean实例
*/
private static final ConcurrentMap<Class<?>, Object> typeBeans =
private static final ConcurrentMap<Class<?>, Object> TYPE_BEANS =
new ConcurrentHashMap<>();
/**
@ -114,11 +114,11 @@ public class Factory {
? clazz.getName()
: component.value();
Object instance = clazz.getDeclaredConstructor().newInstance();
beans.put(name, instance);
typeBeans.put(clazz, instance);
BEANS.put(name, instance);
TYPE_BEANS.put(clazz, instance);
for (Class<?> interfaceClass : clazz.getInterfaces()) {
typeBeans.putIfAbsent(interfaceClass, instance);
TYPE_BEANS.putIfAbsent(interfaceClass, instance);
}
}
}
@ -129,7 +129,7 @@ public class Factory {
* @throws Exception 如果在注入过程中发生异常
*/
private static void injectDependencies() throws Exception {
for (Object bean : beans.values()) {
for (Object bean : BEANS.values()) {
for (Field field : bean.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(InjectBean.class)) {
InjectBean inject = field.getAnnotation(InjectBean.class);
@ -161,17 +161,17 @@ public class Factory {
*/
private static Object findDependency(Class<?> type, String name) {
if (!name.isEmpty()) {
return beans.get(name);
return BEANS.get(name);
}
Object dependency = typeBeans.get(type);
Object dependency = TYPE_BEANS.get(type);
if (dependency != null) {
return dependency;
}
for (Class<?> interfaceType : typeBeans.keySet()) {
for (Class<?> interfaceType : TYPE_BEANS.keySet()) {
if (type.isAssignableFrom(interfaceType)) {
return typeBeans.get(interfaceType);
return TYPE_BEANS.get(interfaceType);
}
}
@ -187,8 +187,8 @@ public class Factory {
public static void add(Object object) {
Class<?> clazz = object.getClass();
String name = clazz.getName();
beans.put(name, object);
typeBeans.put(clazz, object);
BEANS.put(name, object);
TYPE_BEANS.put(clazz, object);
try {
injectDependencies();
} catch (Exception e) {
@ -204,8 +204,8 @@ public class Factory {
* @throws RuntimeException 如果在注入依赖时发生异常
*/
public static void add(String name, Object object) {
beans.put(name, object);
typeBeans.put(object.getClass(), object);
BEANS.put(name, object);
TYPE_BEANS.put(object.getClass(), object);
try {
injectDependencies();
} catch (Exception e) {
@ -221,7 +221,7 @@ public class Factory {
* @return 对应类型的Bean实例未找到则返回null
*/
public static <T> T get(Class<T> objclass) {
return objclass.cast(typeBeans.get(objclass));
return objclass.cast(TYPE_BEANS.get(objclass));
}
/**
@ -233,7 +233,7 @@ public class Factory {
* @return 对应名称和类型的Bean实例未找到则返回null
*/
public static <T> T get(String name, Class<T> objclass) {
return objclass.cast(beans.get(name));
return objclass.cast(BEANS.get(name));
}
/**
@ -243,6 +243,6 @@ public class Factory {
* @return 对应名称的Bean实例未找到则返回null
*/
public static Object get(String name) {
return beans.get(name);
return BEANS.get(name);
}
}

View File

@ -5,6 +5,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author MingLiPro
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentBean {

View File

@ -5,6 +5,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author MingLiPro
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectBean {

View File

@ -19,6 +19,9 @@ import org.springframework.stereotype.Component;
@Component
public class SpringBeanUtil implements ApplicationContextAware {
public static final String PACKAGE_NAME =
SpringBeanUtil.class.getPackage().getName();
/**
* 获取applicationContext
*/

View File

@ -11,6 +11,16 @@ import java.util.stream.Collectors;
*/
public class ByteUtil {
public static final byte ESC_ASC = 0x1A;
public static final byte ESC_DESC = 0x1B;
public static final byte ESC_NONE = 0x00;
public static final byte ESC_START = 0x01;
public static final byte ESC_END = 0x02;
public static final byte ESC_ESC = 0x03;
public static final byte ESC_CONTROL = 0x04;
public static final byte ESC_DATA = 0x05;
public static final byte ESC_RESERVED = 0x06;
/**
* 将字节数组转换为十六进制字符串列表
* <p>

View File

@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentMap;
/**
* ListsAMaps 工具类提供对集合和映射的增强遍历功能
* 包含多个重载的 forEach 方法支持带索引的遍历操作
* @author MingLiPro
*/
public class ForEach {
@ -165,6 +166,191 @@ public class ForEach {
}
}
public static <T> void forEach(Consumer<? super T> action, T... objects) {
int i = 0;
while (i < objects.length) {
T object = objects[i];
action.call(object, i);
i++;
}
}
public static <T> void forEach(T[] objects, Consumer<? super T> action) {
forEach(action, objects);
}
public static <T> void forEach(
T[] objects,
java.util.function.Consumer<? super T> action
) {
forEach(action, objects);
}
public static <T> void forEach(
java.util.function.Consumer<? super T> action,
T... objects
) {
forEach((t, i) -> action.accept(t), objects);
}
public static void forEach(int[] objects, Consumer<Integer> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Integer> action, int... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Integer> action,
int... objects
) {
for (Integer object : objects) {
action.accept(object);
}
}
public static void forEach(byte[] objects, Consumer<Byte> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Byte> action, byte... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Byte> action,
byte... objects
) {
for (Byte object : objects) {
action.accept(object);
}
}
// short类型
public static void forEach(short[] objects, Consumer<Short> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Short> action, short... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Short> action,
short... objects
) {
for (short object : objects) {
action.accept(object);
}
}
// long类型
public static void forEach(long[] objects, Consumer<Long> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Long> action, long... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Long> action,
long... objects
) {
for (long object : objects) {
action.accept(object);
}
}
// float类型
public static void forEach(float[] objects, Consumer<Float> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Float> action, float... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Float> action,
float... objects
) {
for (float object : objects) {
action.accept(object);
}
}
// double类型
public static void forEach(double[] objects, Consumer<Double> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Double> action, double... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Double> action,
double... objects
) {
for (double object : objects) {
action.accept(object);
}
}
// char类型
public static void forEach(char[] objects, Consumer<Character> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Character> action, char... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Character> action,
char... objects
) {
for (char object : objects) {
action.accept(object);
}
}
// boolean类型
public static void forEach(boolean[] objects, Consumer<Boolean> action) {
forEach(action, objects);
}
private static void forEach(Consumer<Boolean> action, boolean... objects) {
for (int i = 0; i < objects.length; i++) {
action.call(objects[i], i);
}
}
private static void forEach(
java.util.function.Consumer<Boolean> action,
boolean... objects
) {
for (boolean object : objects) {
action.accept(object);
}
}
/**
* 自定义消费者接口用于接收元素值和索引
*

View File

@ -39,7 +39,7 @@ public class HashUtils {
MessageDigest digest = MessageDigest.getInstance(algorithm);
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[8192]; // 8KB 缓冲区
byte[] buffer = new byte[8192];
int bytesRead;
// 分块读取文件内容并更新摘要

View File

@ -0,0 +1,37 @@
package com.mingliqiye.utils.jna;
import com.sun.jna.Structure;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/**
* @author MingLiPro
*/
public class FieldStructure extends Structure {
@Override
protected List<String> getFieldOrder() {
List<String> fieldOrderList = new ArrayList<String>();
for (
Class<?> cls = getClass();
!cls.equals(FieldStructure.class);
cls = cls.getSuperclass()
) {
Field[] fields = cls.getDeclaredFields();
int modifiers;
for (Field field : fields) {
modifiers = field.getModifiers();
if (
Modifier.isStatic(modifiers) ||
!Modifier.isPublic(modifiers)
) {
continue;
}
fieldOrderList.add(field.getName());
}
}
return fieldOrderList;
}
}

View File

@ -0,0 +1,15 @@
package com.mingliqiye.utils.jna.time;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.LongByReference;
public interface WinKernel32 extends Library {
static WinKernel32 load() {
return Native.load("kernel32", WinKernel32.class);
}
boolean QueryPerformanceCounter(LongByReference lpPerformanceCount);
boolean QueryPerformanceFrequency(LongByReference lpFrequency);
void GetSystemTimePreciseAsFileTime(byte[] lpSystemTimeAsFileTime);
}

View File

@ -0,0 +1,31 @@
package com.mingliqiye.utils.random;
import com.mingliqiye.utils.collection.ForEach;
/**
* @author MingLiPro
*/
public class RandomBytes {
public static byte[] randomBytes(int length) {
byte[] bytes = new byte[length];
ForEach.forEach(bytes, (b, i) ->
bytes[i] = randomByte((byte) 0x00, (byte) 0xff)
);
return bytes;
}
public static byte randomByte(byte from, byte to) {
int fromInt = from & 0xFF;
int toInt = to & 0xFF;
int randomValue = RandomInt.randomInt(fromInt, toInt);
return (byte) (randomValue & 0xFF);
}
public static byte randomByteNoHave(byte from, byte to) {
int fromInt = from & 0xFF;
int toInt = to & 0xFF;
int randomValue = RandomInt.randomIntNoHave(fromInt, toInt);
return (byte) (randomValue & 0xFF);
}
}

View File

@ -0,0 +1,37 @@
package com.mingliqiye.utils.random;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author MingLiPro
*/
public class RandomInt {
/**
* 生成指定范围内的随机整数
* @param min 最小值包含
* @param max 最大值不包含
* @return 随机整数
*/
public static int randomIntNoHave(int min, int max) {
if (min > max) {
int t = min;
min = max;
max = t;
}
if (min == max) {
return min;
}
return ThreadLocalRandom.current().nextInt(min, max);
}
/**
* 生成指定范围内的随机整数
* @param min 最小值包含
* @param max 最大值包含
* @return 随机整数
*/
public static int randomInt(int min, int max) {
return randomIntNoHave(min, ++max);
}
}

View File

@ -0,0 +1,24 @@
package com.mingliqiye.utils.random;
/**
* @author MingLiPro
*/
public class RandomString {
public static String randomString(int length, String chars) {
String[] charsd = chars.split("");
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int index = RandomInt.randomInt(0, charsd.length - 1);
sb.append(charsd[index]);
}
return sb.toString();
}
public static String randomString(int length) {
return randomString(
length,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
);
}
}

View File

@ -0,0 +1,74 @@
package com.mingliqiye.utils.springboot.autoconfigure;
import com.mingliqiye.utils.collection.ForEach;
import com.mingliqiye.utils.time.DateTime;
import com.mingliqiye.utils.time.Formatter;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author MingLiPro
*/
@Configuration
@EnableConfigurationProperties(AutoConfiguration.class)
public class AutoConfiguration {
private static String banner =
"---------------------------------------------------------\n" +
"| $$\\ $$\\ $$\\ $$\\ $$\\ $$$$$$$$\\ $$$$$$\\ |\n" +
"| $$$\\ $$$ |$$ | $$ | $$ |\\__$$ __|$$ __$$\\ |\n" +
"| $$$$\\ $$$$ |$$ | $$ | $$ | $$ | $$ / \\__| |\n" +
"| $$\\$$\\$$ $$ |$$ | $$ | $$ | $$ | \\$$$$$$\\ |\n" +
"| $$ \\$$$ $$ |$$ | $$ | $$ | $$ | \\____$$\\ |\n" +
"| $$ |\\$ /$$ |$$ | $$ | $$ | $$ | $$\\ $$ | |\n" +
"| $$ | \\_/ $$ |$$$$$$$$\\\\$$$$$$ | $$ | \\$$$$$$ | |\n" +
"| \\__| \\__|\\________|\\______/ \\__| \\______/ |\n";
public AutoConfiguration() throws IOException {
print();
}
public static void main(String[] args) throws IOException {
new AutoConfiguration();
}
public void print() throws IOException {
InputStream inputStream = AutoConfiguration.class.getResourceAsStream(
"/META-INF/meta-data"
);
int readlen;
byte[] buffer = new byte[1024];
StringBuilder metaData = new StringBuilder();
while ((readlen = inputStream.read(buffer)) != -1) {
metaData.append(new String(buffer, 0, readlen));
}
ForEach.forEach(metaData.toString().split("\n"), (s, i) -> {
String[] d = s.trim().split("=", 2);
if (d.length >= 2) {
String content = "| " + d[0] + ": " + d[1];
// 直接计算需要的空格数来对齐
int targetLength = 56; // 为右侧的 | 留出空间
if (content.length() < targetLength) {
int spacesNeeded = targetLength - content.length();
StringBuilder da = new StringBuilder(content);
for (int ia = 0; ia < spacesNeeded; ia++) {
da.append(" ");
}
banner += da + "|\n";
} else {
banner += content.substring(0, targetLength) + "|\n";
}
}
});
System.out.printf(
banner,
DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7)
);
System.out.println(
"---------------------------------------------------------"
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,313 @@
package com.mingliqiye.utils.stream;
import com.mingliqiye.utils.collection.Lists;
import java.util.*;
import java.util.function.*;
/**
* 用于处理键值对的流实现
*
* @author MingLiPro
* @param <K> 键类型
* @param <V> 值类型
*/
public class MapStream<K, V> {
private final List<Map.Entry<K, V>> entries;
/**
* 构造方法
*
* @param entries 包含键值对的列表
*/
private MapStream(List<Map.Entry<K, V>> entries) {
this.entries = entries != null ? entries : Lists.newArrayList();
}
/**
* 从Map创建MapStream
*
* @param map 输入Map
* @param <K> 键类型
* @param <V> 值类型
* @return MapStream实例
*/
public static <K, V> MapStream<K, V> of(Map<K, V> map) {
return new MapStream<>(new ArrayList<>(map.entrySet()));
}
/**
* 从键值对数组创建MapStream
*
* @param entries 键值对数组
* @param <K> 键类型
* @param <V> 值类型
* @return MapStream实例
*/
@SafeVarargs
public static <K, V> MapStream<K, V> of(Map.Entry<K, V>... entries) {
return new MapStream<>(Lists.newArrayList(entries));
}
/**
* 根据键过滤MapStream
*
* @param keyPredicate 键的谓词条件
* @return 过滤后的MapStream
*/
public MapStream<K, V> filterByKey(Predicate<? super K> keyPredicate) {
List<Map.Entry<K, V>> result = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
if (keyPredicate.test(entry.getKey())) {
result.add(entry);
}
}
return new MapStream<>(result);
}
/**
* 根据值过滤MapStream
*
* @param valuePredicate 值的谓词条件
* @return 过滤后的MapStream
*/
public MapStream<K, V> filterByValue(Predicate<? super V> valuePredicate) {
List<Map.Entry<K, V>> result = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
if (valuePredicate.test(entry.getValue())) {
result.add(entry);
}
}
return new MapStream<>(result);
}
/**
* 过滤MapStream
*
* @param predicate 键值对的谓词条件
* @return 过滤后的MapStream
*/
public MapStream<K, V> filter(Predicate<Map.Entry<K, V>> predicate) {
List<Map.Entry<K, V>> result = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
if (predicate.test(entry)) {
result.add(entry);
}
}
return new MapStream<>(result);
}
/**
* 转换键
*
* @param keyMapper 键映射函数
* @param <R> 新的键类型
* @return 转换后的MapStream
*/
public <R> MapStream<R, V> mapKey(
Function<? super K, ? extends R> keyMapper
) {
List<Map.Entry<R, V>> result = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
R newKey = keyMapper.apply(entry.getKey());
result.add(new AbstractMap.SimpleEntry<>(newKey, entry.getValue()));
}
return new MapStream<>(result);
}
/**
* 转换值
*
* @param valueMapper 值映射函数
* @param <R> 新的值类型
* @return 转换后的MapStream
*/
public <R> MapStream<K, R> mapValue(
Function<? super V, ? extends R> valueMapper
) {
List<Map.Entry<K, R>> result = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
R newValue = valueMapper.apply(entry.getValue());
result.add(new AbstractMap.SimpleEntry<>(entry.getKey(), newValue));
}
return new MapStream<>(result);
}
/**
* 转换键值对
*
* @param entryMapper 键值对映射函数
* @param <R> 新的键类型
* @param <S> 新的值类型
* @return 转换后的MapStream
*/
public <R, S> MapStream<R, S> map(
Function<Map.Entry<K, V>, Map.Entry<R, S>> entryMapper
) {
List<Map.Entry<R, S>> result = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
result.add(entryMapper.apply(entry));
}
return new MapStream<>(result);
}
/**
* 将键值对流转换为Map
*
* @return 包含所有键值对的Map
*/
public Map<K, V> toMap() {
Map<K, V> map = new HashMap<>();
for (Map.Entry<K, V> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
/**
* 将键值对流转换为Map指定Map类型和键冲突时的合并函数
*
* @param mapSupplier Map工厂函数
* @param mergeFunction 键冲突合并函数
* @param <M> Map类型
* @return 包含所有键值对的Map
*/
public <M extends Map<K, V>> M toMap(
Supplier<M> mapSupplier,
BinaryOperator<V> mergeFunction
) {
M map = mapSupplier.get();
for (Map.Entry<K, V> entry : entries) {
map.merge(entry.getKey(), entry.getValue(), mergeFunction);
}
return map;
}
/**
* 对每个键值对执行操作
*
* @param action 要执行的操作
*/
public void forEach(BiConsumer<? super K, ? super V> action) {
for (Map.Entry<K, V> entry : entries) {
action.accept(entry.getKey(), entry.getValue());
}
}
/**
* 计算键值对数量
*
* @return 键值对数量
*/
public long count() {
return entries.size();
}
/**
* 获取键的流
*
* @return 键的流
*/
public ListStream<K> keys() {
List<K> keys = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
keys.add(entry.getKey());
}
return ListStream.of(keys);
}
/**
* 获取值的流
*
* @return 值的流
*/
public ListStream<V> values() {
List<V> values = Lists.newArrayList();
for (Map.Entry<K, V> entry : entries) {
values.add(entry.getValue());
}
return ListStream.of(values);
}
/**
* 对键值对进行排序
*
* @param comparator 比较器
* @return 排序后的MapStream
*/
public MapStream<K, V> sorted(Comparator<Map.Entry<K, V>> comparator) {
List<Map.Entry<K, V>> sortedEntries = Lists.newArrayList(entries);
sortedEntries.sort(comparator);
return new MapStream<>(sortedEntries);
}
/**
* 限制键值对数量
*
* @param maxSize 最大数量
* @return 限制后的MapStream
*/
public MapStream<K, V> limit(long maxSize) {
if (maxSize < 0) {
throw new IllegalArgumentException("maxSize must be non-negative");
}
if (maxSize == 0) {
return new MapStream<>(Lists.newArrayList());
}
List<Map.Entry<K, V>> limitedEntries = Lists.newArrayList();
long count = 0;
for (Map.Entry<K, V> entry : entries) {
if (count >= maxSize) {
break;
}
limitedEntries.add(entry);
count++;
}
return new MapStream<>(limitedEntries);
}
/**
* 跳过指定数量的键值对
*
* @param n 要跳过的数量
* @return 跳过后的MapStream
*/
public MapStream<K, V> skip(long n) {
if (n < 0) {
throw new IllegalArgumentException("n must be non-negative");
}
if (n == 0) {
return new MapStream<>(Lists.newArrayList(entries));
}
List<Map.Entry<K, V>> skippedEntries = Lists.newArrayList();
long count = 0;
for (Map.Entry<K, V> entry : entries) {
if (count >= n) {
skippedEntries.add(entry);
}
count++;
}
return new MapStream<>(skippedEntries);
}
@Override
public String toString() {
if (entries.isEmpty()) {
return "MapStream()";
}
StringBuilder sb = new StringBuilder();
sb.append("MapStream(");
for (int i = 0; i < entries.size(); i++) {
Map.Entry<K, V> entry = entries.get(i);
sb.append(entry.getKey()).append("=").append(entry.getValue());
if (i != entries.size() - 1) {
sb.append(", ");
}
}
sb.append(")");
return sb.toString();
}
}

View File

@ -1,5 +1,6 @@
package com.mingliqiye.utils.time;
import com.mingliqiye.utils.jna.time.WinKernel32;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@ -24,11 +25,23 @@ import org.jetbrains.annotations.NotNull;
* @see ZoneId
* @see Instant
*/
@Setter
public final class DateTime {
private static final String version = System.getProperty("java.version");
private static final WinKernel32 WIN_KERNEL_32;
private static final long FILETIME_EPOCH_OFFSET = -116444736000000000L;
private static final long NANOS_PER_100NS = 100;
static {
if (version.startsWith("1.8")) {
WIN_KERNEL_32 = WinKernel32.load();
} else {
WIN_KERNEL_32 = null;
}
}
@Getter
@Setter
private ZoneId zoneId = ZoneId.systemDefault();
@Getter
@ -52,13 +65,40 @@ public final class DateTime {
/**
* 获取当前时间的 DateTime 实例
* 如果运行在 Java 1.8 环境下则通过 WinKernel32 获取高精度时间
*
* @return 返回当前时间的 DateTime 实例
*/
public static DateTime now() {
if (WIN_KERNEL_32 != null) {
byte[] fileTimeBuffer = new byte[8];
WIN_KERNEL_32.GetSystemTimePreciseAsFileTime(fileTimeBuffer);
long fileTime =
(long) (fileTimeBuffer[0] & 0xFF) |
((long) (fileTimeBuffer[1] & 0xFF) << 8) |
((long) (fileTimeBuffer[2] & 0xFF) << 16) |
((long) (fileTimeBuffer[3] & 0xFF) << 24) |
((long) (fileTimeBuffer[4] & 0xFF) << 32) |
((long) (fileTimeBuffer[5] & 0xFF) << 40) |
((long) (fileTimeBuffer[6] & 0xFF) << 48) |
((long) (fileTimeBuffer[7] & 0xFF) << 56);
long unixNanos =
(fileTime + FILETIME_EPOCH_OFFSET) * NANOS_PER_100NS;
Instant instant = Instant.ofEpochSecond(
unixNanos / 1_000_000_000L,
unixNanos % 1_000_000_000L
);
return DateTime.of(
instant.atZone(ZoneId.systemDefault()).toLocalDateTime()
);
}
return new DateTime();
}
public static void main(String[] args) {
System.out.println(DateTime.now());
}
/**
* Date 对象转换为 DateTime 实例
*
@ -215,6 +255,26 @@ public final class DateTime {
return new DateTime(LocalDateTime.of(year, month, day, hour, minute));
}
/**
* FILETIME 转换为 LocalDateTime
*
* @param fileTime FILETIME 时间戳100纳秒单位自1601年1月1日起
* @return 转换后的 LocalDateTime 实例
*/
public static LocalDateTime fileTimeToLocalDateTime(long fileTime) {
// 1. FILETIME (100ns间隔 since 1601) 转换为 Unix 时间戳 (纳秒 since 1970)
long unixNanos = (fileTime + FILETIME_EPOCH_OFFSET) * NANOS_PER_100NS;
// 2. 从纳秒时间戳创建 Instant
Instant instant = Instant.ofEpochSecond(
unixNanos / 1_000_000_000L,
unixNanos % 1_000_000_000L
);
// 3. 转换为系统默认时区的 LocalDateTime
return instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* 根据年秒创建 DateTime 实例
*
@ -292,15 +352,6 @@ public final class DateTime {
);
}
/**
* 设置 LocalDateTime 实例
*
* @param localDateTime LocalDateTime 对象
*/
public void setLocalDateTime(LocalDateTime localDateTime) {
this.localDateTime = localDateTime;
}
/**
* 将当前 DateTime 转换为 Date 对象
*
@ -444,7 +495,6 @@ public final class DateTime {
* @param dateTime 指定时间
* @return 如果当前时间在指定时间之后则返回 true否则返回 false
*/
public boolean isAfter(DateTime dateTime) {
if (dateTime == null) {
return false;
@ -458,7 +508,6 @@ public final class DateTime {
* @param dateTime 指定时间
* @return 如果当前时间在指定时间之前则返回 true否则返回 false
*/
public boolean isBefore(DateTime dateTime) {
if (dateTime == null) {
return false;

View File

@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.mingliqiye.utils.time.DateTime;
import com.mingliqiye.utils.time.Formatter;
import java.io.IOException;
/**

View File

@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.mingliqiye.utils.uuid.UUID;
import com.mingliqiye.utils.uuid.UUIDException;
import java.io.IOException;
/**
@ -24,13 +23,13 @@ public class Jackson {
*
* @param objectMapper ObjectMapper实例用于注册自定义序列化模块
*/
public static void addSerializers(ObjectMapper objectMapper) {
// 创建SimpleModule并添加UUID的序列化器和反序列化器
SimpleModule module = new SimpleModule()
.addSerializer(UUID.class, new UUIDJsonSerializer())
.addDeserializer(UUID.class, new UUIDJsonDeserializer());
objectMapper.registerModule(module);
}
public static void addSerializers(ObjectMapper objectMapper) {
// 创建SimpleModule并添加UUID的序列化器和反序列化器
SimpleModule module = new SimpleModule()
.addSerializer(UUID.class, new UUIDJsonSerializer())
.addDeserializer(UUID.class, new UUIDJsonDeserializer());
objectMapper.registerModule(module);
}
/**
* UUID 反序列化器