From 07739d72dbe6a80e7cda68e48c0c7f28d97d9a77 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 18 Apr 2025 12:12:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=BB=E9=99=A4JDK8=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/v7/ai/AIServiceFactory.java | 4 +- .../hutool/v7/ai/core/AIConfigRegistry.java | 5 +- .../java/cn/hutool/v7/ai/core/BaseConfig.java | 7 +- .../annotation/AnnotationMappingProxy.java | 4 +- .../cn/hutool/v7/core/bean/RecordUtil.java | 64 +------- .../cn/hutool/v7/core/cache/SimpleCache.java | 4 +- .../v7/core/cache/impl/AbstractCache.java | 6 +- .../collection/set/ConcurrentHashSet.java | 17 +- .../v7/core/convert/RegisterConverter.java | 8 +- .../hutool/v7/core/data/CreditCodeUtil.java | 4 +- .../core/date/format/DateFormatManager.java | 6 +- .../v7/core/date/format/DatePattern.java | 36 ++--- .../v7/core/date/format/FormatCache.java | 6 +- .../date/format/parser/FastDateParser.java | 42 +++-- .../cn/hutool/v7/core/func/FunctionPool.java | 61 -------- .../cn/hutool/v7/core/lang/Singleton.java | 4 +- .../java/cn/hutool/v7/core/map/MapUtil.java | 90 +---------- .../concurrent/ConcurrentLinkedHashMap.java | 19 ++- .../map/concurrent/SafeConcurrentHashMap.java | 97 ------------ .../core/map/reference/SoftConcurrentMap.java | 6 +- .../core/map/reference/WeakConcurrentMap.java | 6 +- .../map/reference/WeakKeyConcurrentMap.java | 6 +- .../lookup/ConstructorLookupFactory.java | 67 -------- .../v7/core/reflect/lookup/LookupUtil.java | 7 +- .../stream/TransformableWrappedStream.java | 6 +- .../hutool/v7/core/text/AntPathMatcher.java | 12 +- .../java/cn/hutool/v7/core/text/StrUtil.java | 14 +- .../java/cn/hutool/v7/core/util/JdkUtil.java | 6 - .../hutool/v7/core/func/FunctionPoolTest.java | 55 ------- .../cn/hutool/v7/core/map/Issue2349Test.java | 15 -- .../cn/hutool/v7/core/map/MapUtilTest.java | 147 ++---------------- .../hutool/v7/db/dialect/DialectFactory.java | 4 +- .../main/java/cn/hutool/v7/db/ds/DSPool.java | 4 +- .../cn/hutool/v7/http/html/HtmlFilter.java | 26 ++-- .../cn/hutool/v7/setting/SettingUtil.java | 4 +- .../cn/hutool/v7/setting/profile/Profile.java | 6 +- .../cn/hutool/v7/setting/props/PropsUtil.java | 4 +- 37 files changed, 154 insertions(+), 725 deletions(-) delete mode 100644 hutool-core/src/main/java/cn/hutool/v7/core/func/FunctionPool.java delete mode 100644 hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/SafeConcurrentHashMap.java delete mode 100644 hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/ConstructorLookupFactory.java delete mode 100644 hutool-core/src/test/java/cn/hutool/v7/core/func/FunctionPoolTest.java diff --git a/hutool-ai/src/main/java/cn/hutool/v7/ai/AIServiceFactory.java b/hutool-ai/src/main/java/cn/hutool/v7/ai/AIServiceFactory.java index bb5a649ac..0221feccb 100644 --- a/hutool-ai/src/main/java/cn/hutool/v7/ai/AIServiceFactory.java +++ b/hutool-ai/src/main/java/cn/hutool/v7/ai/AIServiceFactory.java @@ -19,10 +19,10 @@ package cn.hutool.v7.ai; import cn.hutool.v7.ai.core.AIConfig; import cn.hutool.v7.ai.core.AIService; import cn.hutool.v7.ai.core.AIServiceProvider; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import java.util.Map; import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; /** * 创建AIModelService的工厂类 @@ -32,7 +32,7 @@ import java.util.ServiceLoader; */ public class AIServiceFactory { - private static final Map providers = new SafeConcurrentHashMap<>(); + private static final Map providers = new ConcurrentHashMap<>(); // 加载所有 AIModelProvider 实现类 static { diff --git a/hutool-ai/src/main/java/cn/hutool/v7/ai/core/AIConfigRegistry.java b/hutool-ai/src/main/java/cn/hutool/v7/ai/core/AIConfigRegistry.java index c08188e29..afb2b4f49 100644 --- a/hutool-ai/src/main/java/cn/hutool/v7/ai/core/AIConfigRegistry.java +++ b/hutool-ai/src/main/java/cn/hutool/v7/ai/core/AIConfigRegistry.java @@ -16,10 +16,9 @@ package cn.hutool.v7.ai.core; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; - import java.util.Map; import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; /** * AIConfig实现类的加载器 @@ -29,7 +28,7 @@ import java.util.ServiceLoader; */ public class AIConfigRegistry { - private static final Map> configClasses = new SafeConcurrentHashMap<>(); + private static final Map> configClasses = new ConcurrentHashMap<>(); // 加载所有 AIConfig 实现类 static { diff --git a/hutool-ai/src/main/java/cn/hutool/v7/ai/core/BaseConfig.java b/hutool-ai/src/main/java/cn/hutool/v7/ai/core/BaseConfig.java index 55a73c802..52433c806 100644 --- a/hutool-ai/src/main/java/cn/hutool/v7/ai/core/BaseConfig.java +++ b/hutool-ai/src/main/java/cn/hutool/v7/ai/core/BaseConfig.java @@ -16,9 +16,8 @@ package cn.hutool.v7.ai.core; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; - import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Config基础类,定义模型配置的基本属性 @@ -35,7 +34,7 @@ public class BaseConfig implements AIConfig { //具体模型 protected volatile String model; //动态扩展字段 - protected Map additionalConfig = new SafeConcurrentHashMap<>(); + protected Map additionalConfig = new ConcurrentHashMap<>(); @Override public void setApiKey(final String apiKey) { @@ -79,7 +78,7 @@ public class BaseConfig implements AIConfig { @Override public Map getAdditionalConfigMap() { - return new SafeConcurrentHashMap<>(additionalConfig); + return new ConcurrentHashMap<>(additionalConfig); } } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationMappingProxy.java b/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationMappingProxy.java index e069f3daf..67470107b 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationMappingProxy.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/annotation/AnnotationMappingProxy.java @@ -16,7 +16,6 @@ package cn.hutool.v7.core.annotation; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.reflect.method.MethodUtil; import cn.hutool.v7.core.text.CharSequenceUtil; @@ -28,6 +27,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -96,7 +96,7 @@ public final class AnnotationMappingProxy implements Invoc private AnnotationMappingProxy(final AnnotationMapping annotation) { final int methodCount = annotation.getAttributes().length; this.methods = new HashMap<>(methodCount + 5); - this.valueCache = new SafeConcurrentHashMap<>(methodCount); + this.valueCache = new ConcurrentHashMap<>(methodCount); this.mapping = annotation; loadMethods(); } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/bean/RecordUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/bean/RecordUtil.java index 856ad5fb5..ec46d5518 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/bean/RecordUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/bean/RecordUtil.java @@ -17,31 +17,21 @@ package cn.hutool.v7.core.bean; import cn.hutool.v7.core.bean.copier.ValueProvider; -import cn.hutool.v7.core.classloader.ClassLoaderUtil; import cn.hutool.v7.core.reflect.ConstructorUtil; -import cn.hutool.v7.core.reflect.method.MethodUtil; -import cn.hutool.v7.core.util.JdkUtil; -import java.lang.reflect.Method; +import java.lang.reflect.RecordComponent; import java.lang.reflect.Type; import java.util.AbstractMap; import java.util.Map; /** - * java.lang.Record 相关工具类封装
- * 来自于FastJSON2的BeanUtils + * java.lang.Record 相关工具类封装 * - * @author fastjson2, Looly - * @since 6.0.0 + * @author Looly + * @since 7.0.0 */ public class RecordUtil { - private static volatile Class RECORD_CLASS; - - private static volatile Method METHOD_GET_RECORD_COMPONENTS; - private static volatile Method METHOD_COMPONENT_GET_NAME; - private static volatile Method METHOD_COMPONENT_GET_GENERIC_TYPE; - /** * 判断给定类是否为Record类 * @@ -49,27 +39,7 @@ public class RecordUtil { * @return 是否为Record类 */ public static boolean isRecord(final Class clazz) { - if (JdkUtil.JVM_VERSION < 14) { - // JDK14+支持Record类 - return false; - } - final Class superClass = clazz.getSuperclass(); - if (superClass == null) { - return false; - } - - if (RECORD_CLASS == null) { - // 此处不使用同步代码,重复赋值并不影响判断 - final String superclassName = superClass.getName(); - if ("java.lang.Record".equals(superclassName)) { - RECORD_CLASS = superClass; - return true; - } else { - return false; - } - } - - return superClass == RECORD_CLASS; + return null != clazz && clazz.isRecord(); } /** @@ -80,31 +50,11 @@ public class RecordUtil { */ @SuppressWarnings("unchecked") public static Map.Entry[] getRecordComponents(final Class recordClass) { - if (JdkUtil.JVM_VERSION < 14) { - // JDK14+支持Record类 - return new Map.Entry[0]; - } - if (null == METHOD_GET_RECORD_COMPONENTS) { - METHOD_GET_RECORD_COMPONENTS = MethodUtil.getMethod(Class.class, "getRecordComponents"); - } - - final Class recordComponentClass = ClassLoaderUtil.loadClass("java.lang.reflect.RecordComponent"); - if (METHOD_COMPONENT_GET_NAME == null) { - METHOD_COMPONENT_GET_NAME = MethodUtil.getMethod(recordComponentClass, "getName"); - } - if (METHOD_COMPONENT_GET_GENERIC_TYPE == null) { - METHOD_COMPONENT_GET_GENERIC_TYPE = MethodUtil.getMethod(recordComponentClass, "getGenericType"); - } - - final Object[] components = MethodUtil.invoke(recordClass, METHOD_GET_RECORD_COMPONENTS); + final RecordComponent[] components = recordClass.getRecordComponents(); final Map.Entry[] entries = new Map.Entry[components.length]; for (int i = 0; i < components.length; i++) { - entries[i] = new AbstractMap.SimpleEntry<>( - MethodUtil.invoke(components[i], METHOD_COMPONENT_GET_NAME), - MethodUtil.invoke(components[i], METHOD_COMPONENT_GET_GENERIC_TYPE) - ); + entries[i] = new AbstractMap.SimpleEntry<>(components[i].getName(), components[i].getGenericType()); } - return entries; } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/cache/SimpleCache.java b/hutool-core/src/main/java/cn/hutool/v7/core/cache/SimpleCache.java index 0e4422511..12475f01b 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/cache/SimpleCache.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/cache/SimpleCache.java @@ -21,7 +21,6 @@ import cn.hutool.v7.core.func.SerSupplier; import cn.hutool.v7.core.lang.Assert; import cn.hutool.v7.core.lang.mutable.Mutable; import cn.hutool.v7.core.lang.mutable.MutableObj; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.map.reference.WeakConcurrentMap; import java.io.Serializable; @@ -29,6 +28,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; @@ -57,7 +57,7 @@ public class SimpleCache implements Iterable>, Serializabl /** * 写的时候每个key一把锁,降低锁的粒度 */ - protected final Map keyLockMap = new SafeConcurrentHashMap<>(); + protected final Map keyLockMap = new ConcurrentHashMap<>(); /** * 构造,默认使用{@link WeakHashMap}实现缓存自动清理 diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/cache/impl/AbstractCache.java b/hutool-core/src/main/java/cn/hutool/v7/core/cache/impl/AbstractCache.java index 25580523f..3f1c20b73 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/cache/impl/AbstractCache.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/cache/impl/AbstractCache.java @@ -21,11 +21,12 @@ import cn.hutool.v7.core.cache.CacheListener; import cn.hutool.v7.core.func.SerSupplier; import cn.hutool.v7.core.lang.mutable.Mutable; import cn.hutool.v7.core.lang.mutable.MutableObj; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; +import java.io.Serial; import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -44,6 +45,7 @@ import java.util.stream.Collectors; * @author Looly, jodd */ public abstract class AbstractCache implements Cache { + @Serial private static final long serialVersionUID = 1L; /** @@ -54,7 +56,7 @@ public abstract class AbstractCache implements Cache { /** * 写的时候每个key一把锁,降低锁的粒度 */ - protected final Map keyLockMap = new SafeConcurrentHashMap<>(); + protected final Map keyLockMap = new ConcurrentHashMap<>(); /** * 返回缓存容量,{@code 0}表示无大小限制 diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/collection/set/ConcurrentHashSet.java b/hutool-core/src/main/java/cn/hutool/v7/core/collection/set/ConcurrentHashSet.java index 54b89728b..891bc4cb2 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/collection/set/ConcurrentHashSet.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/collection/set/ConcurrentHashSet.java @@ -16,12 +16,12 @@ package cn.hutool.v7.core.collection.set; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; - +import java.io.Serial; import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; /** - * 通过{@link SafeConcurrentHashMap}实现的线程安全HashSet + * 通过{@link ConcurrentHashMap}实现的线程安全HashSet * * @author Looly * @@ -29,6 +29,7 @@ import java.util.Collection; * @since 3.1.0 */ public class ConcurrentHashSet extends SetFromMap { + @Serial private static final long serialVersionUID = 7997886765361607470L; // ----------------------------------------------------------------------------------- Constructor start @@ -37,7 +38,7 @@ public class ConcurrentHashSet extends SetFromMap { * 触发因子为默认的0.75 */ public ConcurrentHashSet() { - super(new SafeConcurrentHashMap<>()); + super(new ConcurrentHashMap<>()); } /** @@ -47,7 +48,7 @@ public class ConcurrentHashSet extends SetFromMap { * @param initialCapacity 初始大小 */ public ConcurrentHashSet(final int initialCapacity) { - super(new SafeConcurrentHashMap<>(initialCapacity)); + super(new ConcurrentHashMap<>(initialCapacity)); } /** @@ -57,7 +58,7 @@ public class ConcurrentHashSet extends SetFromMap { * @param loadFactor 加载因子。此参数决定数据增长时触发的百分比 */ public ConcurrentHashSet(final int initialCapacity, final float loadFactor) { - super(new SafeConcurrentHashMap<>(initialCapacity, loadFactor)); + super(new ConcurrentHashMap<>(initialCapacity, loadFactor)); } /** @@ -68,7 +69,7 @@ public class ConcurrentHashSet extends SetFromMap { * @param concurrencyLevel 线程并发度 */ public ConcurrentHashSet(final int initialCapacity, final float loadFactor, final int concurrencyLevel) { - super(new SafeConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel)); + super(new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel)); } /** @@ -76,7 +77,7 @@ public class ConcurrentHashSet extends SetFromMap { * @param iter {@link Iterable} */ public ConcurrentHashSet(final Iterable iter) { - super(iter instanceof Collection ? new SafeConcurrentHashMap<>(((Collection)iter).size()) : new SafeConcurrentHashMap<>()); + super(iter instanceof Collection ? new ConcurrentHashMap<>(((Collection)iter).size()) : new ConcurrentHashMap<>()); if(iter instanceof Collection) { this.addAll((Collection)iter); }else { diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/convert/RegisterConverter.java b/hutool-core/src/main/java/cn/hutool/v7/core/convert/RegisterConverter.java index b137481df..fc50d8f76 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/convert/RegisterConverter.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/convert/RegisterConverter.java @@ -22,11 +22,11 @@ import cn.hutool.v7.core.lang.Opt; import cn.hutool.v7.core.lang.tuple.Pair; import cn.hutool.v7.core.lang.tuple.Triple; import cn.hutool.v7.core.lang.tuple.Tuple; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.reflect.TypeUtil; import cn.hutool.v7.core.stream.StreamUtil; import javax.xml.datatype.XMLGregorianCalendar; +import java.io.Serial; import java.io.Serializable; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; @@ -38,6 +38,7 @@ import java.nio.file.Path; import java.time.*; import java.time.temporal.TemporalAccessor; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicLongArray; @@ -55,6 +56,7 @@ import java.util.concurrent.atomic.AtomicReference; * @since 6.0.0 */ public class RegisterConverter extends ConverterWithRoot implements Serializable { + @Serial private static final long serialVersionUID = 1L; /** @@ -169,7 +171,7 @@ public class RegisterConverter extends ConverterWithRoot implements Serializable if (null == customConverterMap) { synchronized (this) { if (null == customConverterMap) { - customConverterMap = new SafeConcurrentHashMap<>(); + customConverterMap = new ConcurrentHashMap<>(); } } } @@ -201,7 +203,7 @@ public class RegisterConverter extends ConverterWithRoot implements Serializable * @return 默认转换器 */ private static Map, Converter> initDefault(final Converter rootConverter) { - final Map, Converter> converterMap = new SafeConcurrentHashMap<>(64); + final Map, Converter> converterMap = new ConcurrentHashMap<>(64); // 包装类转换器 converterMap.put(Character.class, CharacterConverter.INSTANCE); diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/data/CreditCodeUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/data/CreditCodeUtil.java index e7e67e7ff..4c88a1add 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/data/CreditCodeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/data/CreditCodeUtil.java @@ -16,13 +16,13 @@ package cn.hutool.v7.core.data; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.regex.PatternPool; import cn.hutool.v7.core.regex.ReUtil; import cn.hutool.v7.core.text.StrUtil; import cn.hutool.v7.core.util.RandomUtil; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; /** @@ -62,7 +62,7 @@ public class CreditCodeUtil { private static final Map CODE_INDEX_MAP; static { - CODE_INDEX_MAP = new SafeConcurrentHashMap<>(); + CODE_INDEX_MAP = new ConcurrentHashMap<>(); for (int i = 0; i < BASE_CODE_ARRAY.length; i++) { CODE_INDEX_MAP.put(BASE_CODE_ARRAY[i], i); } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DateFormatManager.java b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DateFormatManager.java index eeb6c5218..2af5c88ec 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DateFormatManager.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DateFormatManager.java @@ -18,11 +18,11 @@ package cn.hutool.v7.core.date.format; import cn.hutool.v7.core.date.DateUtil; import cn.hutool.v7.core.lang.Assert; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import java.time.temporal.TemporalAccessor; import java.util.Date; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; /** @@ -70,8 +70,8 @@ public class DateFormatManager { * 构造 */ public DateFormatManager() { - formatterMap = new SafeConcurrentHashMap<>(); - parserMap = new SafeConcurrentHashMap<>(); + formatterMap = new ConcurrentHashMap<>(); + parserMap = new ConcurrentHashMap<>(); // Hutool预设的几种自定义格式 registerFormatter(FORMAT_SECONDS, (date) -> String.valueOf(Math.floorDiv(date.getTime(), 1000L))); diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DatePattern.java b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DatePattern.java index 752d120ab..1f1357bd9 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DatePattern.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/DatePattern.java @@ -17,11 +17,11 @@ package cn.hutool.v7.core.date.format; import cn.hutool.v7.core.date.DateException; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import java.io.IOException; import java.text.DateFormatSymbols; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** @@ -296,14 +296,11 @@ public class DatePattern { * @return a new rule with the correct padding */ protected static NumberRule selectNumberRule(final int field, final int padding) { - switch (padding) { - case 1: - return new UnpaddedNumberField(field); - case 2: - return new TwoDigitNumberField(field); - default: - return new PaddedNumberField(field, padding); - } + return switch (padding) { + case 1 -> new UnpaddedNumberField(field); + case 2 -> new TwoDigitNumberField(field); + default -> new PaddedNumberField(field, padding); + }; } // Rules @@ -901,16 +898,12 @@ public class DatePattern { * @return a Iso8601_Rule that can format TimeZone String of length {@code tokenLen}. If no such rule exists, an IllegalArgumentException will be thrown. */ static Iso8601_Rule getRule(final int tokenLen) { - switch (tokenLen) { - case 1: - return Iso8601_Rule.ISO8601_HOURS; - case 2: - return Iso8601_Rule.ISO8601_HOURS_MINUTES; - case 3: - return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; - default: - throw new IllegalArgumentException("invalid number of X"); - } + return switch (tokenLen) { + case 1 -> Iso8601_Rule.ISO8601_HOURS; + case 2 -> Iso8601_Rule.ISO8601_HOURS_MINUTES; + case 3 -> Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; + default -> throw new IllegalArgumentException("invalid number of X"); + }; } final int length; @@ -1045,7 +1038,7 @@ public class DatePattern { } } - private static final ConcurrentMap C_TIME_ZONE_DISPLAY_CACHE = new SafeConcurrentHashMap<>(7); + private static final ConcurrentMap C_TIME_ZONE_DISPLAY_CACHE = new ConcurrentHashMap<>(7); /** *

@@ -1110,8 +1103,7 @@ public class DatePattern { if (this == obj) { return true; } - if (obj instanceof TimeZoneDisplayKey) { - final TimeZoneDisplayKey other = (TimeZoneDisplayKey) obj; + if (obj instanceof TimeZoneDisplayKey other) { return mTimeZone.equals(other.mTimeZone) && mStyle == other.mStyle && mLocale.equals(other.mLocale); } return false; diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/FormatCache.java b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/FormatCache.java index 37fa6f3d2..09a934ae9 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/FormatCache.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/FormatCache.java @@ -18,13 +18,13 @@ package cn.hutool.v7.core.date.format; import cn.hutool.v7.core.lang.Assert; import cn.hutool.v7.core.lang.tuple.Tuple; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import java.text.DateFormat; import java.text.Format; import java.text.SimpleDateFormat; import java.util.Locale; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** @@ -40,9 +40,9 @@ abstract class FormatCache { */ static final int NONE = -1; - private final ConcurrentMap cInstanceCache = new SafeConcurrentHashMap<>(7); + private final ConcurrentMap cInstanceCache = new ConcurrentHashMap<>(7); - private static final ConcurrentMap C_DATE_TIME_INSTANCE_CACHE = new SafeConcurrentHashMap<>(7); + private static final ConcurrentMap C_DATE_TIME_INSTANCE_CACHE = new ConcurrentHashMap<>(7); /** * 使用默认的pattern、timezone和locale获得缓存中的实例 diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/parser/FastDateParser.java b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/parser/FastDateParser.java index 67afd6b56..b4b700ada 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/date/format/parser/FastDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/date/format/parser/FastDateParser.java @@ -20,14 +20,15 @@ import cn.hutool.v7.core.date.DateException; import cn.hutool.v7.core.date.format.FastDateFormat; import cn.hutool.v7.core.date.format.FastDatePrinter; import cn.hutool.v7.core.date.format.SimpleDateBasic; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.StrUtil; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serial; import java.text.DateFormatSymbols; import java.text.ParsePosition; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -40,6 +41,7 @@ import java.util.regex.Pattern; * @since 2.16.2 */ public class FastDateParser extends SimpleDateBasic implements PositionDateParser { + @Serial private static final long serialVersionUID = -3199383897950947498L; static final Locale JAPANESE_IMPERIAL = new Locale("ja", "JP", "JP"); @@ -221,6 +223,7 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse * @throws IOException if there is an IO issue. * @throws ClassNotFoundException if a class cannot be found. */ + @Serial private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); @@ -380,8 +383,6 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse */ private Strategy getStrategy(final char f, final int width, final Calendar definingCalendar) { switch (f) { - default: - throw new IllegalArgumentException("Format '" + f + "' not supported"); case 'D': return DAY_OF_YEAR_STRATEGY; case 'E': @@ -428,6 +429,8 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse //$FALL-THROUGH$ case 'z': return getLocaleSpecificStrategy(Calendar.ZONE_OFFSET, definingCalendar); + default: + throw new IllegalArgumentException("Format '" + f + "' not supported"); } } @@ -443,7 +446,7 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse private static ConcurrentMap getCache(final int field) { synchronized (CACHES) { if (CACHES[field] == null) { - CACHES[field] = new SafeConcurrentHashMap<>(3); + CACHES[field] = new ConcurrentHashMap<>(3); } return CACHES[field]; } @@ -669,15 +672,14 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse final TzInfo standard = new TzInfo(tz, false); TzInfo tzInfo = standard; for (int i = 1; i < zoneNames.length; ++i) { - switch (i) { - case 3: // offset 3 is long daylight savings (or summertime) name + tzInfo = switch (i) { + case 3 -> // offset 3 is long daylight savings (or summertime) name // offset 4 is the short summertime name - tzInfo = new TzInfo(tz, true); - break; - case 5: // offset 5 starts additional names, probably standard time - tzInfo = standard; - break; - } + new TzInfo(tz, true); + case 5 -> // offset 5 starts additional names, probably standard time + standard; + default -> tzInfo; + }; if (zoneNames[i] != null) { final String key = zoneNames[i].toLowerCase(locale); // ignore the data associated with duplicates supplied in @@ -747,16 +749,12 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse * @return a ISO8601TimeZoneStrategy that can format TimeZone String of length {@code tokenLen}. If no such strategy exists, an IllegalArgumentException will be thrown. */ static Strategy getStrategy(final int tokenLen) { - switch (tokenLen) { - case 1: - return ISO_8601_1_STRATEGY; - case 2: - return ISO_8601_2_STRATEGY; - case 3: - return ISO_8601_3_STRATEGY; - default: - throw new IllegalArgumentException("invalid number of X"); - } + return switch (tokenLen) { + case 1 -> ISO_8601_1_STRATEGY; + case 2 -> ISO_8601_2_STRATEGY; + case 3 -> ISO_8601_3_STRATEGY; + default -> throw new IllegalArgumentException("invalid number of X"); + }; } } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/func/FunctionPool.java b/hutool-core/src/main/java/cn/hutool/v7/core/func/FunctionPool.java deleted file mode 100644 index e8758a3cb..000000000 --- a/hutool-core/src/main/java/cn/hutool/v7/core/func/FunctionPool.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2013-2025 Hutool Team and hutool.cn - * - * 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. - */ - -package cn.hutool.v7.core.func; - -import cn.hutool.v7.core.reflect.ConstructorUtil; -import cn.hutool.v7.core.util.JdkUtil; - -import java.lang.reflect.Constructor; -import java.util.function.BiFunction; - -/** - * 常用Lambda函数封装
- * 提供常用对象方法的Lambda包装,减少Lambda初始化时间。 - * - * @author Looly - */ -@SuppressWarnings("unchecked") -public class FunctionPool { - - /** - * 通过{@code String(char[] value, boolean share)}这个内部构造生成一个Lambda函数
- * 此函数通过传入char[],实现zero-copy的String创建,效率很高。但是要求传入的char[]不可以在其他地方修改。
- * 此函数只支持JKDK8 - */ - public static final BiFunction STRING_CREATOR_JDK8; - - static { - final Constructor constructor = ConstructorUtil.getConstructor(String.class, char[].class, boolean.class); - STRING_CREATOR_JDK8 = JdkUtil.IS_JDK8 ? LambdaFactory.build(BiFunction.class, constructor) : null; - } - - /** - * 通过{@code String(char[] value, boolean share)}这个内部构造创建String对象。
- * 此函数通过传入char[],实现zero-copy的String创建,效率很高。但是要求传入的char[]不可以在其他地方修改。 - * - * @param value char[]值,注意这个数组不可修改!! - * @return String - */ - public static String createString(final char[] value) { - if(JdkUtil.IS_JDK8){ - return STRING_CREATOR_JDK8.apply(value, true); - } else { - // TODO JDK9+优化 - return new String(value); - } - } -} diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/lang/Singleton.java b/hutool-core/src/main/java/cn/hutool/v7/core/lang/Singleton.java index 2ef638a32..e2d8afaa4 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/lang/Singleton.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/lang/Singleton.java @@ -18,11 +18,11 @@ package cn.hutool.v7.core.lang; import cn.hutool.v7.core.array.ArrayUtil; import cn.hutool.v7.core.func.SerSupplier; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.reflect.ConstructorUtil; import cn.hutool.v7.core.text.StrUtil; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -33,7 +33,7 @@ import java.util.stream.Collectors; */ public final class Singleton { - private static final SafeConcurrentHashMap POOL = new SafeConcurrentHashMap<>(); + private static final ConcurrentHashMap POOL = new ConcurrentHashMap<>(); private Singleton() { } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/map/MapUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/map/MapUtil.java index 167a7e2cd..6110d97de 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/map/MapUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/map/MapUtil.java @@ -23,14 +23,12 @@ import cn.hutool.v7.core.collection.iter.ArrayIter; import cn.hutool.v7.core.collection.iter.IterUtil; import cn.hutool.v7.core.func.SerConsumer3; import cn.hutool.v7.core.lang.Assert; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.reflect.ConstructorUtil; import cn.hutool.v7.core.text.StrUtil; import cn.hutool.v7.core.util.ObjUtil; import java.util.*; import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; import java.util.function.*; import java.util.stream.Collectors; @@ -196,45 +194,6 @@ public class MapUtil extends MapGetUtil { return new IdentityHashMap<>(size); } - /** - * 新建一个初始容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} 的{@link SafeConcurrentHashMap} - * - * @param key的类型 - * @param value的类型 - * @return {@link SafeConcurrentHashMap} - */ - public static ConcurrentHashMap newSafeConcurrentHashMap() { - return new SafeConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); - } - - /** - * 新建一个{@link SafeConcurrentHashMap} - * - * @param size 初始容量,当传入的容量小于等于0时,容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} - * @param key的类型 - * @param value的类型 - * @return {@link SafeConcurrentHashMap} - */ - public static ConcurrentHashMap newSafeConcurrentHashMap(final int size) { - final int initCapacity = size <= 0 ? DEFAULT_INITIAL_CAPACITY : size; - return new SafeConcurrentHashMap<>(initCapacity); - } - - /** - * 传入一个Map将其转化为{@link SafeConcurrentHashMap}类型 - * - * @param map map - * @param key的类型 - * @param value的类型 - * @return {@link SafeConcurrentHashMap} - */ - public static ConcurrentHashMap newSafeConcurrentHashMap(final Map map) { - if (isEmpty(map)) { - return new ConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); - } - return new SafeConcurrentHashMap<>(map); - } - /** * 创建Map
* 传入抽象Map{@link AbstractMap}和{@link Map}类将默认创建{@link HashMap} @@ -430,11 +389,9 @@ public class MapUtil extends MapGetUtil { final HashMap map = new HashMap<>((int) (array.length * 1.5)); for (int i = 0; i < array.length; i++) { final Object object = array[i]; - if (object instanceof Map.Entry) { - final Map.Entry entry = (Map.Entry) object; + if (object instanceof Map.Entry entry) { map.put(entry.getKey(), entry.getValue()); - } else if (object instanceof Object[]) { - final Object[] entry = (Object[]) object; + } else if (object instanceof Object[] entry) { if (entry.length > 1) { map.put(entry[0], entry[1]); } @@ -447,8 +404,7 @@ public class MapUtil extends MapGetUtil { map.put(key, value); } } - } else if (object instanceof Iterator) { - final Iterator iter = ((Iterator) object); + } else if (object instanceof Iterator iter) { if (iter.hasNext()) { final Object key = iter.next(); if (iter.hasNext()) { @@ -882,9 +838,8 @@ public class MapUtil extends MapGetUtil { return null; } - if (map instanceof TreeMap) { + if (map instanceof TreeMap result) { // 已经是可排序Map,此时只有比较器一致才返回原map - final TreeMap result = (TreeMap) map; if (null == comparator || comparator.equals(result.comparator())) { return result; } @@ -1358,43 +1313,6 @@ public class MapUtil extends MapGetUtil { return map; } - /** - * 如果 key 对应的 value 不存在,则使用获取 mappingFunction 重新计算后的值,并保存为该 key 的 value,否则返回 value。
- * 解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题。(issues#2349)
- * A temporary workaround for Java 8 specific performance issue JDK-8161372 .
- * This class should be removed once we drop Java 8 support. - * - *

- * 注意此方法只能用于JDK8 - *

- * - * @param 键类型 - * @param 值类型 - * @param map Map,一般用于线程安全的Map - * @param key 键 - * @param mappingFunction 值计算函数 - * @return 值 - * @see https://bugs.openjdk.java.net/browse/JDK-8161372 - */ - public static V computeIfAbsentForJdk8(final Map map, final K key, final Function mappingFunction) { - V value = map.get(key); - if (null == value) { - value = mappingFunction.apply(key); - final V res = map.putIfAbsent(key, value); - if (null != res) { - // issues#I6RVMY - // 如果旧值存在,说明其他线程已经赋值成功,putIfAbsent没有执行,返回旧值 - return res; - } - // 如果旧值不存在,说明赋值成功,返回当前值 - - // Dubbo的解决方式,判空后调用依旧无法解决死循环问题 - // 见:Issue2349Test - //value = map.computeIfAbsent(key, mappingFunction); - } - return value; - } - /** * 将一个Map按照固定大小拆分成多个子Map * diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/ConcurrentLinkedHashMap.java b/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/ConcurrentLinkedHashMap.java index 5153542da..078f730b2 100755 --- a/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/ConcurrentLinkedHashMap.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/ConcurrentLinkedHashMap.java @@ -23,6 +23,7 @@ import cn.hutool.v7.core.util.RuntimeUtil; import java.io.InvalidObjectException; import java.io.ObjectInputStream; +import java.io.Serial; import java.io.Serializable; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -214,7 +215,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap // The data store and its maximum capacity concurrencyLevel = builder.concurrencyLevel; capacity = new AtomicLong(Math.min(builder.capacity, MAXIMUM_CAPACITY)); - data = new SafeConcurrentHashMap<>(builder.initialCapacity, 0.75f, concurrencyLevel); + data = new ConcurrentHashMap<>(builder.initialCapacity, 0.75f, concurrencyLevel); // The eviction support weigher = builder.weigher; @@ -1139,7 +1140,6 @@ public final class ConcurrentLinkedHashMap extends AbstractMap * A node contains the key, the weighted value, and the linkage pointers on * the page-replacement algorithm's data structures. */ - @SuppressWarnings("serial") static final class Node extends AtomicReference> implements Linked> { final K key; @@ -1382,6 +1382,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap * An entry that allows updates to write through to the map. */ final class WriteThroughEntry extends SimpleEntry { + @Serial private static final long serialVersionUID = 1; WriteThroughEntry(final Node node) { @@ -1394,6 +1395,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap return super.setValue(value); } + @Serial Object writeReplace() { return new SimpleEntry<>(this); } @@ -1402,13 +1404,12 @@ public final class ConcurrentLinkedHashMap extends AbstractMap /** * A weigher that enforces that the selector falls within a valid range. */ - static final class BoundedEntryWeigher implements EntryWeigher, Serializable { + record BoundedEntryWeigher(EntryWeigher weigher) implements EntryWeigher, Serializable { + @Serial private static final long serialVersionUID = 1; - final EntryWeigher weigher; - BoundedEntryWeigher(final EntryWeigher weigher) { + BoundedEntryWeigher { Assert.notNull(weigher); - this.weigher = weigher; } @Override @@ -1418,6 +1419,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap return weight; } + @Serial Object writeReplace() { return weigher; } @@ -1436,12 +1438,15 @@ public final class ConcurrentLinkedHashMap extends AbstractMap /* ---------------- Serialization Support -------------- */ + @Serial private static final long serialVersionUID = 1; + @Serial Object writeReplace() { return new SerializationProxy<>(this); } + @Serial private void readObject(final ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -1468,6 +1473,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap weigher = map.weigher; } + @Serial Object readResolve() { final ConcurrentLinkedHashMap map = new Builder() .concurrencyLevel(concurrencyLevel) @@ -1479,6 +1485,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap return map; } + @Serial private static final long serialVersionUID = 1; } diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/SafeConcurrentHashMap.java b/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/SafeConcurrentHashMap.java deleted file mode 100644 index 1e1fa3587..000000000 --- a/hutool-core/src/main/java/cn/hutool/v7/core/map/concurrent/SafeConcurrentHashMap.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2013-2025 Hutool Team and hutool.cn - * - * 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. - */ - -package cn.hutool.v7.core.map.concurrent; - -import cn.hutool.v7.core.map.MapUtil; -import cn.hutool.v7.core.util.JdkUtil; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; - -/** - * 安全的ConcurrentHashMap实现
- * 此类用于解决在JDK8中调用{@link ConcurrentHashMap#computeIfAbsent(Object, Function)}可能造成的死循环问题。
- * 见:issues#2349
- *

- * 相关bug见:https://bugs.openjdk.java.net/browse/JDK-8161372 - * - * @param 键类型 - * @param 值类型 - */ -public class SafeConcurrentHashMap extends ConcurrentHashMap { - private static final long serialVersionUID = 1L; - - // region == 构造 == - - /** - * 构造,默认初始大小(16) - */ - public SafeConcurrentHashMap() { - super(); - } - - /** - * 构造 - * - * @param initialCapacity 预估初始大小 - */ - public SafeConcurrentHashMap(final int initialCapacity) { - super(initialCapacity); - } - - /** - * 构造 - * - * @param m 初始键值对 - */ - public SafeConcurrentHashMap(final Map m) { - super(m); - } - - /** - * 构造 - * - * @param initialCapacity 初始容量 - * @param loadFactor 增长系数 - */ - public SafeConcurrentHashMap(final int initialCapacity, final float loadFactor) { - super(initialCapacity, loadFactor); - } - - /** - * 构造 - * - * @param initialCapacity 初始容量 - * @param loadFactor 增长系数 - * @param concurrencyLevel 并发级别,即Segment的个数 - */ - public SafeConcurrentHashMap(final int initialCapacity, - final float loadFactor, final int concurrencyLevel) { - super(initialCapacity, loadFactor, concurrencyLevel); - } - // endregion == 构造 == - - @Override - public V computeIfAbsent(final K key, final Function mappingFunction) { - if (JdkUtil.IS_JDK8) { - return MapUtil.computeIfAbsentForJdk8(this, key, mappingFunction); - } else { - return super.computeIfAbsent(key, mappingFunction); - } - } -} diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/SoftConcurrentMap.java b/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/SoftConcurrentMap.java index b68b9f1ee..8176fe8fb 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/SoftConcurrentMap.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/SoftConcurrentMap.java @@ -18,9 +18,10 @@ package cn.hutool.v7.core.map.reference; import cn.hutool.v7.core.lang.ref.Ref; import cn.hutool.v7.core.lang.ref.SoftObj; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; +import java.io.Serial; import java.lang.ref.ReferenceQueue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** @@ -33,13 +34,14 @@ import java.util.concurrent.ConcurrentMap; * @since 6.0.0 */ public class SoftConcurrentMap extends ReferenceConcurrentMap { + @Serial private static final long serialVersionUID = 1L; /** * 构造 */ public SoftConcurrentMap() { - this(new SafeConcurrentHashMap<>()); + this(new ConcurrentHashMap<>()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakConcurrentMap.java b/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakConcurrentMap.java index bc7dbbbad..5057b48a7 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakConcurrentMap.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakConcurrentMap.java @@ -18,9 +18,10 @@ package cn.hutool.v7.core.map.reference; import cn.hutool.v7.core.lang.ref.Ref; import cn.hutool.v7.core.lang.ref.WeakObj; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; +import java.io.Serial; import java.lang.ref.ReferenceQueue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** @@ -33,13 +34,14 @@ import java.util.concurrent.ConcurrentMap; * @since 6.0.0 */ public class WeakConcurrentMap extends ReferenceConcurrentMap { + @Serial private static final long serialVersionUID = 1L; /** * 构造 */ public WeakConcurrentMap() { - this(new SafeConcurrentHashMap<>()); + this(new ConcurrentHashMap<>()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakKeyConcurrentMap.java b/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakKeyConcurrentMap.java index 905640885..556f2180a 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakKeyConcurrentMap.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/map/reference/WeakKeyConcurrentMap.java @@ -19,9 +19,10 @@ package cn.hutool.v7.core.map.reference; import cn.hutool.v7.core.lang.ref.Ref; import cn.hutool.v7.core.lang.ref.StrongObj; import cn.hutool.v7.core.lang.ref.WeakObj; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; +import java.io.Serial; import java.lang.ref.ReferenceQueue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** @@ -34,13 +35,14 @@ import java.util.concurrent.ConcurrentMap; * @since 6.0.0 */ public class WeakKeyConcurrentMap extends ReferenceConcurrentMap { + @Serial private static final long serialVersionUID = 1L; /** * 构造 */ public WeakKeyConcurrentMap() { - this(new SafeConcurrentHashMap<>()); + this(new ConcurrentHashMap<>()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/ConstructorLookupFactory.java b/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/ConstructorLookupFactory.java deleted file mode 100644 index 105e442e9..000000000 --- a/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/ConstructorLookupFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2013-2025 Hutool Team and hutool.cn - * - * 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. - */ - -package cn.hutool.v7.core.reflect.lookup; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; - -/** - * jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}
- * 在调用findSpecial和unreflectSpecial时会出现权限不够问题,抛出"no private access for invokespecial"异常
- * 所以通过反射创建MethodHandles.Lookup解决该问题。 - *

- * 参考:https://blog.csdn.net/u013202238/article/details/108687086 - * - * @author Looly - * @since 6.0.0 - */ -public class ConstructorLookupFactory implements LookupFactory { - - private static final int ALLOWED_MODES = MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED - | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC; - - private final Constructor lookupConstructor; - - /** - * 构造 - */ - public ConstructorLookupFactory() { - this.lookupConstructor = createLookupConstructor(); - } - - @Override - public MethodHandles.Lookup lookup(final Class callerClass) { - try { - return lookupConstructor.newInstance(callerClass, ALLOWED_MODES); - } catch (final Exception e) { - throw new IllegalStateException("no 'Lookup(Class, int)' method in java.lang.invoke.MethodHandles.", e); - } - } - - private static Constructor createLookupConstructor() { - final Constructor constructor; - try { - constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); - } catch (final NoSuchMethodException e) { - //可能是jdk8 以下版本 - throw new IllegalStateException( - "There is no 'Lookup(Class, int)' constructor in java.lang.invoke.MethodHandles.", e); - } - constructor.setAccessible(true); - return constructor; - } -} diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/LookupUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/LookupUtil.java index 9ac36d7c2..d0cff9900 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/LookupUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/reflect/lookup/LookupUtil.java @@ -21,7 +21,6 @@ import cn.hutool.v7.core.lang.caller.CallerUtil; import cn.hutool.v7.core.reflect.ConstructorUtil; import cn.hutool.v7.core.reflect.ModifierUtil; import cn.hutool.v7.core.text.StrUtil; -import cn.hutool.v7.core.util.JdkUtil; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -50,11 +49,7 @@ public class LookupUtil { private static final LookupFactory factory; static { - if (JdkUtil.IS_JDK8) { - factory = new ConstructorLookupFactory(); - } else { - factory = new MethodLookupFactory(); - } + factory = new MethodLookupFactory(); } // region ----- lookup diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/stream/TransformableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/v7/core/stream/TransformableWrappedStream.java index f6b0bc0ce..3e795bab5 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/stream/TransformableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/stream/TransformableWrappedStream.java @@ -24,9 +24,9 @@ import cn.hutool.v7.core.lang.Console; import cn.hutool.v7.core.lang.mutable.MutableInt; import cn.hutool.v7.core.lang.mutable.MutableObj; import cn.hutool.v7.core.map.MapUtil; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.*; @@ -238,7 +238,7 @@ public interface TransformableWrappedStream EasyStream distinct(final Function keyExtractor) { Objects.requireNonNull(keyExtractor); if (isParallel()) { - final SafeConcurrentHashMap exists = new SafeConcurrentHashMap<>(); + final ConcurrentHashMap exists = new ConcurrentHashMap<>(); // 标记是否出现过null值,用于保留第一个出现的null // 由于ConcurrentHashMap的key不能为null,所以用此变量来标记 final AtomicBoolean hasNull = new AtomicBoolean(false); @@ -321,7 +321,7 @@ public interface TransformableWrappedStream result = unwrap(); if (ArrayUtil.isNotEmpty(obj)) { diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/text/AntPathMatcher.java b/hutool-core/src/main/java/cn/hutool/v7/core/text/AntPathMatcher.java index 0a53f38d7..96afbf081 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/text/AntPathMatcher.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/text/AntPathMatcher.java @@ -17,14 +17,10 @@ package cn.hutool.v7.core.text; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.split.SplitUtil; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -78,9 +74,9 @@ public class AntPathMatcher { private volatile Boolean cachePatterns; - private final Map tokenizedPatternCache = new SafeConcurrentHashMap<>(256); + private final Map tokenizedPatternCache = new ConcurrentHashMap<>(256); - private final Map stringMatcherCache = new SafeConcurrentHashMap<>(256); + private final Map stringMatcherCache = new ConcurrentHashMap<>(256); /** diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java index d45b04472..e5b546206 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java @@ -17,7 +17,6 @@ package cn.hutool.v7.core.text; import cn.hutool.v7.core.array.ArrayUtil; -import cn.hutool.v7.core.func.FunctionPool; import cn.hutool.v7.core.text.split.SplitUtil; import cn.hutool.v7.core.util.CharsetUtil; @@ -102,7 +101,7 @@ public class StrUtil extends CharSequenceUtil implements StrPool { if (null == obj) { return true; } else if (obj instanceof CharSequence) { - return 0 == ((CharSequence) obj).length(); + return ((CharSequence) obj).isEmpty(); } return false; } @@ -231,17 +230,6 @@ public class StrUtil extends CharSequenceUtil implements StrPool { } return charset.decode(data).toString(); } - - /** - * JDK8中,通过{@code String(char[] value, boolean share)}这个内部构造创建String对象。
- * 此函数通过传入char[],实现zero-copy的String创建,效率很高。但是要求传入的char[]不可以在其他地方修改。 - * - * @param value char[]值,注意这个数组不可修改!! - * @return String - */ - public static String strFast(final char[] value) { - return FunctionPool.createString(value); - } // endregion /** diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/util/JdkUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/util/JdkUtil.java index 4c0750761..aa37b67f8 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/util/JdkUtil.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/util/JdkUtil.java @@ -29,11 +29,6 @@ public class JdkUtil { * JDK版本 */ public static final int JVM_VERSION; - /** - * 是否JDK8
- * 由于Hutool基于JDK8编译,当使用JDK版本低于8时,不支持。 - */ - public static final boolean IS_JDK8; /** * 是否大于等于JDK17 */ @@ -56,7 +51,6 @@ public class JdkUtil { static { // JVM版本 JVM_VERSION = _getJvmVersion(); - IS_JDK8 = 8 == JVM_VERSION; IS_AT_LEAST_JDK17 = JVM_VERSION >= 17; // JVM名称 diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/func/FunctionPoolTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/func/FunctionPoolTest.java deleted file mode 100644 index 1560454e7..000000000 --- a/hutool-core/src/test/java/cn/hutool/v7/core/func/FunctionPoolTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2013-2025 Hutool Team and hutool.cn - * - * 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. - */ - -package cn.hutool.v7.core.func; - -import cn.hutool.v7.core.collection.ListUtil; -import cn.hutool.v7.core.date.DateUtil; -import cn.hutool.v7.core.date.StopWatch; -import cn.hutool.v7.core.util.RandomUtil; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; - -public class FunctionPoolTest { - - @Test - public void createStringTest() { - // 预热 - FunctionPool.createString("123".toCharArray()); - - // 测试数据 - final ArrayList list = ListUtil.of(); - for (int i = 0; i < 100000; i++) { - list.add(RandomUtil.randomStringLower(100).toCharArray()); - } - - final StopWatch stopWatch = DateUtil.createStopWatch(); - stopWatch.start("copy creator"); - for (final char[] value : list) { - new String(value); - } - stopWatch.stop(); - - stopWatch.start("zero copy creator"); - for (final char[] value : list) { - FunctionPool.createString(value); - } - stopWatch.stop(); - - //Console.log(stopWatch.prettyPrint()); - } -} diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/map/Issue2349Test.java b/hutool-core/src/test/java/cn/hutool/v7/core/map/Issue2349Test.java index 1ba1e5ed6..58d68d5e4 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/map/Issue2349Test.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/map/Issue2349Test.java @@ -16,7 +16,6 @@ package cn.hutool.v7.core.map; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledForJreRange; @@ -25,20 +24,6 @@ import java.util.concurrent.ConcurrentHashMap; public class Issue2349Test { - @Test - @EnabledForJreRange(max = org.junit.jupiter.api.condition.JRE.JAVA_8) - public void computeIfAbsentTest() { - // https://blog.csdn.net/xiaochao_bos/article/details/103789991 - // 使用ConcurrentHashMap会造成死循环 - // SafeConcurrentHashMap用于修复此问题 - final ConcurrentHashMap map = new SafeConcurrentHashMap<>(16); - map.computeIfAbsent("AaAa", key -> map.computeIfAbsent("BBBB", key2 -> 42)); - - Assertions.assertEquals(2, map.size()); - Assertions.assertEquals(Integer.valueOf(42), map.get("AaAa")); - Assertions.assertEquals(Integer.valueOf(42), map.get("BBBB")); - } - @Test @EnabledForJreRange(min = org.junit.jupiter.api.condition.JRE.JAVA_9) public void issue11986ForJava17Test() { diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/map/MapUtilTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/map/MapUtilTest.java index 674679bb8..8a905fc39 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/map/MapUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/map/MapUtilTest.java @@ -16,18 +16,17 @@ package cn.hutool.v7.core.map; -import lombok.Builder; -import lombok.Data; import cn.hutool.v7.core.convert.ConvertUtil; import cn.hutool.v7.core.lang.Opt; import cn.hutool.v7.core.reflect.TypeReference; import cn.hutool.v7.core.text.StrUtil; +import lombok.Builder; +import lombok.Data; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.io.Serial; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -94,7 +93,7 @@ public class MapUtilTest { // 下单用户,Queue表示正在 .排队. 抢我抢不到的二次元周边! final Queue customers = new ArrayDeque<>(Arrays.asList("刑部尚书手工耿", "木瓜大盗大漠叔", "竹鼠发烧找华农", "朴实无华朱一旦")); // 分组 - final List groups = Stream.iterate(0L, i -> ++i).limit(4).map(i -> Group.builder().id(i).build()).collect(Collectors.toList()); + final List groups = Stream.iterate(0L, i -> ++i).limit(4).map(i -> Group.builder().id(i).build()).toList(); // 如你所见,它是一个map,key由用户id,value由用户组成 final Map idUserMap = Stream.iterate(0L, i -> ++i).limit(4).map(i -> User.builder().id(i).name(customers.poll()).build()).collect(Collectors.toMap(User::getId, Function.identity())); // 如你所见,它是一个map,key由分组id,value由用户ids组成,典型的多对多关系 @@ -259,18 +258,6 @@ public class MapUtilTest { Assertions.assertTrue(v2s.contains("李四")); } - @Test - void computeIfAbsentForJdk8Test() { - // https://github.com/apache/dubbo/issues/11986 - final ConcurrentHashMap map = new ConcurrentHashMap<>(); - // // map.computeIfAbsent("AaAa", key->map.computeIfAbsent("BBBB",key2->42)); - MapUtil.computeIfAbsentForJdk8(map, "AaAa", key -> map.computeIfAbsent("BBBB", key2 -> 42)); - - Assertions.assertEquals(2, map.size()); - Assertions.assertEquals(Integer.valueOf(42), map.get("AaAa")); - Assertions.assertEquals(Integer.valueOf(42), map.get("BBBB")); - } - @Test void createMapTest() { final Map map = MapUtil.createMap(MapUtil.view(new HashMap<>()).getClass()); @@ -365,7 +352,8 @@ public class MapUtilTest { @Test public void issue3162Test() { - final Map map = new HashMap() { + final Map map = new HashMap<>() { + @Serial private static final long serialVersionUID = 1L; { @@ -456,122 +444,6 @@ public class MapUtilTest { assertEquals(3, result.get(1).size()); } - - // ---------MapUtil.computeIfAbsentForJdk8 - @Test - public void computeIfAbsentForJdk8KeyExistsReturnsExistingValue() { - final Map map = new HashMap<>(); - map.put("key", 10); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(10, result); - } - - @Test - public void computeIfAbsentForJdk8KeyDoesNotExistComputesAndInsertsValue() { - final Map map = new HashMap<>(); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(20, result); - assertEquals(20, map.get("key")); - } - - @Test - public void computeIfAbsentForJdk8ConcurrentInsertReturnsOldValue() { - final ConcurrentHashMap concurrentMap = new ConcurrentHashMap<>(); - concurrentMap.put("key", 30); - final AtomicInteger counter = new AtomicInteger(0); - - // 模拟并发插入 - concurrentMap.computeIfAbsent("key", k -> { - counter.incrementAndGet(); - return 40; - }); - - final Integer result = MapUtil.computeIfAbsentForJdk8(concurrentMap, "key", k -> 50); - assertEquals(30, result); - assertEquals(30, concurrentMap.get("key")); - assertEquals(0, counter.get()); - } - - @Test - public void computeIfAbsentForJdk8NullValueComputesAndInsertsValue() { - final Map map = new HashMap<>(); - map.put("key", null); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(20, result); - assertEquals(20, map.get("key")); - } - - //--------MapUtil.computeIfAbsent - @Test - public void computeIfAbsentKeyExistsReturnsExistingValue() { - final Map map = new HashMap<>(); - map.put("key", 10); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(10, result); - } - - @Test - public void computeIfAbsentKeyDoesNotExistComputesAndInsertsValue() { - final Map map = new HashMap<>(); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(20, result); - assertEquals(20, map.get("key")); - } - - @Test - public void computeIfAbsentConcurrentInsertReturnsOldValue() { - final ConcurrentHashMap concurrentMap = new ConcurrentHashMap<>(); - concurrentMap.put("key", 30); - final AtomicInteger counter = new AtomicInteger(0); - - // 模拟并发插入 - concurrentMap.computeIfAbsent("key", k -> { - counter.incrementAndGet(); - return 40; - }); - - final Integer result = MapUtil.computeIfAbsentForJdk8(concurrentMap, "key", k -> 50); - assertEquals(30, result); - assertEquals(30, concurrentMap.get("key")); - assertEquals(0, counter.get()); - } - - @Test - public void computeIfAbsentNullValueComputesAndInsertsValue() { - final Map map = new HashMap<>(); - map.put("key", null); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(20, result); - assertEquals(20, map.get("key")); - } - - @Test - public void computeIfAbsentEmptyMapInsertsValue() { - final Map map = new HashMap<>(); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "newKey", k -> 100); - assertEquals(100, result); - assertEquals(100, map.get("newKey")); - } - - @Test - public void computeIfAbsentJdk8KeyExistsReturnsExistingValue() { - final Map map = new HashMap<>(); - // 假设JdkUtil.ISJDK8为true - map.put("key", 10); - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(10, result); - } - - @Test - public void computeIfAbsentJdk8KeyDoesNotExistComputesAndInsertsValue() { - final Map map = new HashMap<>(); - // 假设JdkUtil.ISJDK8为true - final Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); - assertEquals(20, result); - assertEquals(20, map.get("key")); - } - - //----------valuesOfKeys @Test public void valuesOfKeysEmptyIteratorReturnsEmptyList() { @@ -591,6 +463,7 @@ public class MapUtilTest { map.put("b", "2"); map.put("c", "3"); final Iterator iterator = new ArrayList() { + @Serial private static final long serialVersionUID = -4593258366224032110L; { @@ -600,6 +473,7 @@ public class MapUtilTest { }.iterator(); final ArrayList result = MapUtil.valuesOfKeys(map, iterator); assertEquals(new ArrayList() { + @Serial private static final long serialVersionUID = 7218152799308667271L; { @@ -616,6 +490,7 @@ public class MapUtilTest { map.put("b", "2"); map.put("c", "3"); final Iterator iterator = new ArrayList() { + @Serial private static final long serialVersionUID = -5479427021989481058L; { @@ -625,6 +500,7 @@ public class MapUtilTest { }.iterator(); final ArrayList result = MapUtil.valuesOfKeys(map, iterator); assertEquals(new ArrayList() { + @Serial private static final long serialVersionUID = 4390715387901549136L; { @@ -641,6 +517,7 @@ public class MapUtilTest { map.put("b", "2"); map.put("c", "3"); final Iterator iterator = new ArrayList() { + @Serial private static final long serialVersionUID = 8510595063492828968L; { @@ -651,7 +528,9 @@ public class MapUtilTest { }.iterator(); final ArrayList result = MapUtil.valuesOfKeys(map, iterator); assertEquals(new ArrayList() { + @Serial private static final long serialVersionUID = 6383576410597048337L; + { add("1"); add(null); diff --git a/hutool-db/src/main/java/cn/hutool/v7/db/dialect/DialectFactory.java b/hutool-db/src/main/java/cn/hutool/v7/db/dialect/DialectFactory.java index 3f34ca001..9f5bedb03 100644 --- a/hutool-db/src/main/java/cn/hutool/v7/db/dialect/DialectFactory.java +++ b/hutool-db/src/main/java/cn/hutool/v7/db/dialect/DialectFactory.java @@ -16,7 +16,6 @@ package cn.hutool.v7.db.dialect; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.StrUtil; import cn.hutool.v7.db.config.DbConfig; import cn.hutool.v7.db.dialect.impl.*; @@ -26,6 +25,7 @@ import cn.hutool.v7.log.LogUtil; import javax.sql.DataSource; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * 方言工厂类 @@ -34,7 +34,7 @@ import java.util.Map; */ public class DialectFactory { - private static final Map DIALECT_POOL = new SafeConcurrentHashMap<>(); + private static final Map DIALECT_POOL = new ConcurrentHashMap<>(); private DialectFactory() { } diff --git a/hutool-db/src/main/java/cn/hutool/v7/db/ds/DSPool.java b/hutool-db/src/main/java/cn/hutool/v7/db/ds/DSPool.java index 6806ceafa..319d1c065 100644 --- a/hutool-db/src/main/java/cn/hutool/v7/db/ds/DSPool.java +++ b/hutool-db/src/main/java/cn/hutool/v7/db/ds/DSPool.java @@ -19,7 +19,6 @@ package cn.hutool.v7.db.ds; import cn.hutool.v7.core.io.IoUtil; import cn.hutool.v7.core.lang.Singleton; import cn.hutool.v7.core.map.MapUtil; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.StrUtil; import cn.hutool.v7.db.config.ConfigParser; import cn.hutool.v7.db.config.DbConfig; @@ -29,6 +28,7 @@ import cn.hutool.v7.log.LogUtil; import java.io.Closeable; import java.util.Collection; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * 数据源池,用于支持多数据源。
@@ -84,7 +84,7 @@ public class DSPool implements Closeable { public DSPool(final ConfigParser configParser, final DSFactory factory) { this.configParser = null != configParser ? configParser : SettingConfigParser.of(); this.factory = null != factory ? factory : DSUtil.getDefaultDsFactory(); - this.pool = new SafeConcurrentHashMap<>(); + this.pool = new ConcurrentHashMap<>(); } /** diff --git a/hutool-http/src/main/java/cn/hutool/v7/http/html/HtmlFilter.java b/hutool-http/src/main/java/cn/hutool/v7/http/html/HtmlFilter.java index 295a08571..ee09bbed7 100644 --- a/hutool-http/src/main/java/cn/hutool/v7/http/html/HtmlFilter.java +++ b/hutool-http/src/main/java/cn/hutool/v7/http/html/HtmlFilter.java @@ -17,14 +17,10 @@ package cn.hutool.v7.http.html; import cn.hutool.v7.core.lang.Console; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.CharUtil; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,8 +73,8 @@ public final class HtmlFilter { private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); // @xxx could grow large... maybe use sesat's ReferenceMap - private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new SafeConcurrentHashMap<>(); - private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new SafeConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); /** * set of allowed html elements, along with allowed attributes for each element @@ -294,7 +290,7 @@ public final class HtmlFilter { private String escapeComments(final String s) { final Matcher m = P_COMMENTS.matcher(s); - final StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); if (m.find()) { final String match = m.group(1); // (.*?) m.appendReplacement(buf, Matcher.quoteReplacement("")); @@ -334,7 +330,7 @@ public final class HtmlFilter { private String checkTags(String s) { final Matcher m = P_TAGS.matcher(s); - final StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); while (m.find()) { String replaceStr = m.group(1); replaceStr = processTag(replaceStr); @@ -477,7 +473,7 @@ public final class HtmlFilter { } private String decodeEntities(String s) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); Matcher m = P_ENTITY.matcher(s); while (m.find()) { @@ -488,7 +484,7 @@ public final class HtmlFilter { m.appendTail(buf); s = buf.toString(); - buf = new StringBuffer(); + buf = new StringBuilder(); m = P_ENTITY_UNICODE.matcher(s); while (m.find()) { final String match = m.group(1); @@ -498,7 +494,7 @@ public final class HtmlFilter { m.appendTail(buf); s = buf.toString(); - buf = new StringBuffer(); + buf = new StringBuilder(); m = P_ENCODE.matcher(s); while (m.find()) { final String match = m.group(1); @@ -513,7 +509,7 @@ public final class HtmlFilter { } private String validateEntities(final String s) { - final StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); // validate entities throughout the string final Matcher m = P_VALID_ENTITIES.matcher(s); @@ -529,7 +525,7 @@ public final class HtmlFilter { private String encodeQuotes(final String s) { if (encodeQuotes) { - final StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); final Matcher m = P_VALID_QUOTES.matcher(s); while (m.find()) { final String one = m.group(1); // (>|^) diff --git a/hutool-setting/src/main/java/cn/hutool/v7/setting/SettingUtil.java b/hutool-setting/src/main/java/cn/hutool/v7/setting/SettingUtil.java index 565ae37ed..0a5e9e9c7 100644 --- a/hutool-setting/src/main/java/cn/hutool/v7/setting/SettingUtil.java +++ b/hutool-setting/src/main/java/cn/hutool/v7/setting/SettingUtil.java @@ -18,10 +18,10 @@ package cn.hutool.v7.setting; import cn.hutool.v7.core.io.file.FileNameUtil; import cn.hutool.v7.core.io.resource.NoResourceException; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.StrUtil; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Setting工具类
@@ -33,7 +33,7 @@ public class SettingUtil { /** * 配置文件缓存 */ - private static final Map SETTING_MAP = new SafeConcurrentHashMap<>(); + private static final Map SETTING_MAP = new ConcurrentHashMap<>(); /** * 获取当前环境下的配置文件
diff --git a/hutool-setting/src/main/java/cn/hutool/v7/setting/profile/Profile.java b/hutool-setting/src/main/java/cn/hutool/v7/setting/profile/Profile.java index 3d0ceba3d..805d60cfe 100644 --- a/hutool-setting/src/main/java/cn/hutool/v7/setting/profile/Profile.java +++ b/hutool-setting/src/main/java/cn/hutool/v7/setting/profile/Profile.java @@ -17,13 +17,14 @@ package cn.hutool.v7.setting.profile; import cn.hutool.v7.core.lang.Assert; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.StrUtil; import cn.hutool.v7.setting.Setting; +import java.io.Serial; import java.io.Serializable; import java.nio.charset.Charset; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Profile可以让我们定义一系列的配置信息,然后指定其激活条件。
@@ -40,6 +41,7 @@ import java.util.Map; * */ public class Profile implements Serializable { + @Serial private static final long serialVersionUID = -4189955219454008744L; /** 默认环境 */ @@ -52,7 +54,7 @@ public class Profile implements Serializable { /** 是否使用变量 */ private boolean useVar; /** 配置文件缓存 */ - private final Map settingMap = new SafeConcurrentHashMap<>(); + private final Map settingMap = new ConcurrentHashMap<>(); // -------------------------------------------------------------------------------- Constructor start /** diff --git a/hutool-setting/src/main/java/cn/hutool/v7/setting/props/PropsUtil.java b/hutool-setting/src/main/java/cn/hutool/v7/setting/props/PropsUtil.java index 5ddd862d3..cb7b2ac0c 100644 --- a/hutool-setting/src/main/java/cn/hutool/v7/setting/props/PropsUtil.java +++ b/hutool-setting/src/main/java/cn/hutool/v7/setting/props/PropsUtil.java @@ -18,10 +18,10 @@ package cn.hutool.v7.setting.props; import cn.hutool.v7.core.io.file.FileNameUtil; import cn.hutool.v7.core.io.resource.NoResourceException; -import cn.hutool.v7.core.map.concurrent.SafeConcurrentHashMap; import cn.hutool.v7.core.text.StrUtil; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Props工具类
@@ -35,7 +35,7 @@ public class PropsUtil { /** * 配置文件缓存 */ - private static final Map propsMap = new SafeConcurrentHashMap<>(); + private static final Map propsMap = new ConcurrentHashMap<>(); /** * 获取当前环境下的配置文件