mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
bdc964c882
commit
b090fbdd3d
@ -15,8 +15,8 @@ package org.dromara.hutool.core.annotation;
|
||||
import org.dromara.hutool.core.annotation.elements.HierarchicalAnnotatedElements;
|
||||
import org.dromara.hutool.core.annotation.elements.MetaAnnotatedElement;
|
||||
import org.dromara.hutool.core.annotation.elements.RepeatableMetaAnnotatedElement;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
@ -133,7 +133,7 @@ import java.util.stream.Stream;
|
||||
* <p><strong>缓存</strong>
|
||||
* <p>为了避免注解以及{@link AnnotatedElement}层级结构解析过程中的大量反射调用,
|
||||
* 工具类为{@link AnnotatedElement}及其元注解信息进行了缓存。<br>
|
||||
* 缓存功能默认基于{@link WeakKeyConcurrentMap}实现,会在gc时自动回收部分缓存数据。
|
||||
* 缓存功能默认基于{@link WeakConcurrentMap}实现,会在gc时自动回收部分缓存数据。
|
||||
* 但是若有必要,也可以调用{@link #clearCaches()}方法主动清空缓存。
|
||||
*
|
||||
* @author huangchengxing
|
||||
@ -150,22 +150,22 @@ public class AnnotatedElementUtil {
|
||||
/**
|
||||
* 支持属性解析的{@link MetaAnnotatedElement}缓存
|
||||
*/
|
||||
private static final Map<AnnotatedElement, MetaAnnotatedElement<ResolvedAnnotationMapping>> RESOLVED_ELEMENT_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final Map<AnnotatedElement, MetaAnnotatedElement<ResolvedAnnotationMapping>> RESOLVED_ELEMENT_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 不支持属性解析的{@link MetaAnnotatedElement}缓存
|
||||
*/
|
||||
private static final Map<AnnotatedElement, MetaAnnotatedElement<GenericAnnotationMapping>> ELEMENT_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final Map<AnnotatedElement, MetaAnnotatedElement<GenericAnnotationMapping>> ELEMENT_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 不支持属性解析的{@link RepeatableMetaAnnotatedElement}缓存
|
||||
*/
|
||||
private static final Map<AnnotatedElement, RepeatableMetaAnnotatedElement<ResolvedAnnotationMapping>> RESOLVED_REPEATABLE_ELEMENT_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final Map<AnnotatedElement, RepeatableMetaAnnotatedElement<ResolvedAnnotationMapping>> RESOLVED_REPEATABLE_ELEMENT_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 不支持属性解析的{@link RepeatableMetaAnnotatedElement}缓存
|
||||
*/
|
||||
private static final Map<AnnotatedElement, RepeatableMetaAnnotatedElement<GenericAnnotationMapping>> REPEATABLE_ELEMENT_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final Map<AnnotatedElement, RepeatableMetaAnnotatedElement<GenericAnnotationMapping>> REPEATABLE_ELEMENT_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
// region ========== find ==========
|
||||
|
||||
|
@ -19,7 +19,7 @@ import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.func.LambdaInfo;
|
||||
import org.dromara.hutool.core.func.LambdaUtil;
|
||||
import org.dromara.hutool.core.func.SerFunction;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.FieldUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.text.CharSequenceUtil;
|
||||
@ -50,7 +50,7 @@ public class AnnotationUtil {
|
||||
/**
|
||||
* 直接声明的注解缓存
|
||||
*/
|
||||
private static final Map<AnnotatedElement, Annotation[]> DECLARED_ANNOTATIONS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final Map<AnnotatedElement, Annotation[]> DECLARED_ANNOTATIONS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 获取直接声明的注解,若已有缓存则从缓存中获取
|
||||
|
@ -14,7 +14,7 @@ package org.dromara.hutool.core.annotation;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.text.CharSequenceUtil;
|
||||
|
||||
@ -337,7 +337,7 @@ public interface RepeatableAnnotationCollector {
|
||||
/**
|
||||
* 可重复注解对应的方法缓存
|
||||
*/
|
||||
private final Map<Class<? extends Annotation>, Object> repeatableMethodCache = new WeakKeyConcurrentMap<>();
|
||||
private final Map<Class<? extends Annotation>, Object> repeatableMethodCache = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -447,7 +447,7 @@ public interface RepeatableAnnotationCollector {
|
||||
/**
|
||||
* 可重复注解对应的方法缓存
|
||||
*/
|
||||
private final Map<Class<? extends Annotation>, Object> repeatableMethodCache = new WeakKeyConcurrentMap<>();
|
||||
private final Map<Class<? extends Annotation>, Object> repeatableMethodCache = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 构造
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.core.bean;
|
||||
|
||||
import org.dromara.hutool.core.func.SerSupplier;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
/**
|
||||
* Bean属性缓存<br>
|
||||
@ -27,7 +27,7 @@ public enum BeanDescCache {
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private final WeakKeyConcurrentMap<Class<?>, BeanDesc> bdCache = new WeakKeyConcurrentMap<>();
|
||||
private final WeakConcurrentMap<Class<?>, BeanDesc> bdCache = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 获得属性名和{@link BeanDesc}Map映射
|
||||
|
@ -13,8 +13,8 @@
|
||||
package org.dromara.hutool.core.bean;
|
||||
|
||||
import org.dromara.hutool.core.func.SerSupplier;
|
||||
import org.dromara.hutool.core.map.reference.ReferenceKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.ReferenceConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.Map;
|
||||
@ -31,8 +31,8 @@ public enum BeanInfoCache {
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private final WeakKeyConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> pdCache = new WeakKeyConcurrentMap<>();
|
||||
private final WeakKeyConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> ignoreCasePdCache = new WeakKeyConcurrentMap<>();
|
||||
private final WeakConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> pdCache = new WeakConcurrentMap<>();
|
||||
private final WeakConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> ignoreCasePdCache = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 获得属性名和{@link PropertyDescriptor}Map映射
|
||||
@ -86,10 +86,10 @@ public enum BeanInfoCache {
|
||||
* 根据是否忽略字段名的大小写,返回不用Cache对象
|
||||
*
|
||||
* @param ignoreCase 是否忽略大小写
|
||||
* @return {@link ReferenceKeyConcurrentMap}
|
||||
* @return {@link ReferenceConcurrentMap}
|
||||
* @since 5.4.1
|
||||
*/
|
||||
private ReferenceKeyConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> getCache(final boolean ignoreCase) {
|
||||
private ReferenceConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> getCache(final boolean ignoreCase) {
|
||||
return ignoreCase ? ignoreCasePdCache : pdCache;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.mutable.Mutable;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableObj;
|
||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
@ -33,7 +33,7 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 简单缓存,无超时实现,默认使用{@link WeakKeyConcurrentMap}实现缓存自动清理
|
||||
* 简单缓存,无超时实现,默认使用{@link WeakConcurrentMap}实现缓存自动清理
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
@ -57,7 +57,7 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
|
||||
* 构造,默认使用{@link WeakHashMap}实现缓存自动清理
|
||||
*/
|
||||
public SimpleCache() {
|
||||
this(new WeakKeyConcurrentMap<>());
|
||||
this(new WeakConcurrentMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,9 +15,8 @@ package org.dromara.hutool.core.cache.impl;
|
||||
import org.dromara.hutool.core.cache.CacheListener;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.lang.mutable.Mutable;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import org.dromara.hutool.core.lang.ref.Ref;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
/**
|
||||
* 弱引用缓存<br>
|
||||
@ -39,16 +38,18 @@ public class WeakCache<K, V> extends TimedCache<K, V>{
|
||||
* @param timeout 超时时常,单位毫秒,-1或0表示无限制
|
||||
*/
|
||||
public WeakCache(final long timeout) {
|
||||
super(timeout, new WeakKeyConcurrentMap<>());
|
||||
super(timeout, new WeakConcurrentMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeakCache<K, V> setListener(final CacheListener<K, V> listener) {
|
||||
super.setListener(listener);
|
||||
|
||||
final WeakKeyConcurrentMap<Mutable<K>, CacheObj<K, V>> map = (WeakKeyConcurrentMap<Mutable<K>, CacheObj<K, V>>) this.cacheMap;
|
||||
final WeakConcurrentMap<Mutable<K>, CacheObj<K, V>> map = (WeakConcurrentMap<Mutable<K>, CacheObj<K, V>>) this.cacheMap;
|
||||
// WeakKey回收之后,key对应的值已经是null了,因此此处的key也为null
|
||||
map.setPurgeListener((key, value)-> listener.onRemove(Opt.ofNullable(key).map(Reference::get).map(Mutable::get).get(), value.getValue()));
|
||||
map.setPurgeListener((key, value)-> listener.onRemove(
|
||||
Opt.ofNullable(key).map(Ref::get).map(Mutable::get).get(),
|
||||
Opt.ofNullable(value).map(Ref::get).map(CacheObj::getValue).get()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ import org.dromara.hutool.core.convert.AbstractConverter;
|
||||
import org.dromara.hutool.core.convert.ConvertException;
|
||||
import org.dromara.hutool.core.lang.EnumItem;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.reflect.ModifierUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.util.EnumUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@ -42,7 +42,7 @@ public class EnumConverter extends AbstractConverter {
|
||||
*/
|
||||
public static final EnumConverter INSTANCE = new EnumConverter();
|
||||
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Map<Class<?>, Method>> VALUE_OF_METHOD_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Map<Class<?>, Method>> VALUE_OF_METHOD_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(final Class<?> targetClass, final Object value) {
|
||||
|
@ -15,8 +15,9 @@ package org.dromara.hutool.core.func;
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.*;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.core.reflect.ReflectUtil;
|
||||
import org.dromara.hutool.core.reflect.lookup.LookupUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodTypeUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
@ -37,7 +38,7 @@ public class LambdaFactory {
|
||||
throw new IllegalAccessException();
|
||||
}
|
||||
|
||||
private static final Map<MutableEntry<Class<?>, Executable>, Object> CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final Map<MutableEntry<Class<?>, Executable>, Object> CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 构建Lambda
|
||||
|
@ -17,10 +17,10 @@ import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.ClassDescUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.reflect.ModifierUtil;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.invoke.SerializedLambda;
|
||||
@ -37,7 +37,7 @@ import java.util.function.*;
|
||||
*/
|
||||
public class LambdaUtil {
|
||||
|
||||
private static final WeakKeyConcurrentMap<Object, LambdaInfo> CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Object, LambdaInfo> CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 通过对象的方法或类的静态方法引用,获取lambda实现类
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
package org.dromara.hutool.core.lang.intern;
|
||||
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@ -25,7 +25,7 @@ import java.lang.ref.WeakReference;
|
||||
*/
|
||||
public class WeakIntern<T> implements Intern<T> {
|
||||
|
||||
private final WeakKeyConcurrentMap<T, WeakReference<T>> cache = new WeakKeyConcurrentMap<>();
|
||||
private final WeakConcurrentMap<T, WeakReference<T>> cache = new WeakConcurrentMap<>();
|
||||
|
||||
@Override
|
||||
public T intern(final T sample) {
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.lang.ref;
|
||||
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 虚引用对象,在GC时发现虚引用对象,会将{@link PhantomReference}插入{@link ReferenceQueue}。 <br>
|
||||
* 此时对象未被真正回收,要等到{@link ReferenceQueue}被真正处理后才会被回收。
|
||||
*
|
||||
* @param <T> 键类型
|
||||
*/
|
||||
public class PhantomObj<T> extends PhantomReference<T> implements Ref<T>{
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param obj 原始对象
|
||||
* @param queue {@link ReferenceQueue}
|
||||
*/
|
||||
public PhantomObj(final T obj, final ReferenceQueue<? super T> queue) {
|
||||
super(obj, queue);
|
||||
hashCode = Objects.hashCode(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
} else if (other instanceof PhantomObj) {
|
||||
return ObjUtil.equals(((PhantomObj<?>) other).get(), get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.lang.ref;
|
||||
|
||||
/**
|
||||
* 针对{@link java.lang.ref.Reference}的接口定义,用于扩展功能<br>
|
||||
* 例如提供自定义的无需回收对象
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Ref<T> {
|
||||
|
||||
/**
|
||||
* 获取引用的原始对象
|
||||
*
|
||||
* @return 原始对象
|
||||
*/
|
||||
T get();
|
||||
}
|
@ -21,6 +21,10 @@ import java.lang.ref.ReferenceQueue;
|
||||
* @author looly
|
||||
*/
|
||||
public enum ReferenceType {
|
||||
/**
|
||||
* 强引用,不回收
|
||||
*/
|
||||
STRONG,
|
||||
/**
|
||||
* 软引用,在GC报告内存不足时会被GC回收
|
||||
*/
|
||||
|
@ -79,4 +79,16 @@ public class ReferenceUtil {
|
||||
public static <T> T get(final Reference<T> obj) {
|
||||
return ObjUtil.apply(obj, Reference::get);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code null}全的解包获取原始对象
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @param obj Ref对象
|
||||
* @return 原始对象 or {@code null}
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T> T get(final Ref<T> obj) {
|
||||
return ObjUtil.apply(obj, Ref::get);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @param <T> 键类型
|
||||
*/
|
||||
public class SoftObj<T> extends SoftReference<T> {
|
||||
public class SoftObj<T> extends SoftReference<T> implements Ref<T>{
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.lang.ref;
|
||||
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 弱引用对象,在GC时发现弱引用会回收其对象
|
||||
*
|
||||
* @param <T> 键类型
|
||||
*/
|
||||
public class StrongObj<T> implements Ref<T> {
|
||||
|
||||
private final T obj;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param obj 原始对象
|
||||
*/
|
||||
public StrongObj(final T obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return this.obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
} else if (other instanceof StrongObj) {
|
||||
return ObjUtil.equals(((StrongObj<?>) other).get(), get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @param <T> 键类型
|
||||
*/
|
||||
public class WeakObj<T> extends WeakReference<T> {
|
||||
public class WeakObj<T> extends WeakReference<T> implements Ref<T>{
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
|
@ -12,8 +12,9 @@
|
||||
|
||||
package org.dromara.hutool.core.map.reference;
|
||||
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.lang.ref.Ref;
|
||||
import org.dromara.hutool.core.lang.ref.ReferenceUtil;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.Reference;
|
||||
@ -34,13 +35,13 @@ import java.util.function.Function;
|
||||
public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V>, Iterable<Map.Entry<K, V>>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final ConcurrentMap<Reference<K>, Reference<V>> raw;
|
||||
final ConcurrentMap<Ref<K>, Ref<V>> raw;
|
||||
private final ReferenceQueue<K> lastKeyQueue;
|
||||
private final ReferenceQueue<V> lastValueQueue;
|
||||
/**
|
||||
* 回收监听
|
||||
*/
|
||||
private BiConsumer<Reference<? extends K>, Reference<? extends V>> purgeListener;
|
||||
private BiConsumer<Ref<? extends K>, Ref<? extends V>> purgeListener;
|
||||
|
||||
// region 构造
|
||||
|
||||
@ -49,7 +50,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
*
|
||||
* @param raw {@link ConcurrentMap}实现
|
||||
*/
|
||||
public ReferenceConcurrentMap(final ConcurrentMap<Reference<K>, Reference<V>> raw) {
|
||||
public ReferenceConcurrentMap(final ConcurrentMap<Ref<K>, Ref<V>> raw) {
|
||||
this.raw = raw;
|
||||
lastKeyQueue = new ReferenceQueue<>();
|
||||
lastValueQueue = new ReferenceQueue<>();
|
||||
@ -61,7 +62,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
*
|
||||
* @param purgeListener 监听函数
|
||||
*/
|
||||
public void setPurgeListener(final BiConsumer<Reference<? extends K>, Reference<? extends V>> purgeListener) {
|
||||
public void setPurgeListener(final BiConsumer<Ref<? extends K>, Ref<? extends V>> purgeListener) {
|
||||
this.purgeListener = purgeListener;
|
||||
}
|
||||
|
||||
@ -98,14 +99,14 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public V put(final K key, final V value) {
|
||||
this.purgeStale();
|
||||
final Reference<V> vReference = this.raw.put(wrapKey(key), wrapValue(value));
|
||||
final Ref<V> vReference = this.raw.put(wrapKey(key), wrapValue(value));
|
||||
return unwrap(vReference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V putIfAbsent(final K key, final V value) {
|
||||
this.purgeStale();
|
||||
final Reference<V> vReference = this.raw.putIfAbsent(wrapKey(key), wrapValue(value));
|
||||
final Ref<V> vReference = this.raw.putIfAbsent(wrapKey(key), wrapValue(value));
|
||||
return unwrap(vReference);
|
||||
}
|
||||
|
||||
@ -117,7 +118,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public V replace(final K key, final V value) {
|
||||
this.purgeStale();
|
||||
final Reference<V> vReference = this.raw.replace(wrapKey(key), wrapValue(value));
|
||||
final Ref<V> vReference = this.raw.replace(wrapKey(key), wrapValue(value));
|
||||
return unwrap(vReference);
|
||||
}
|
||||
|
||||
@ -136,7 +137,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public V computeIfAbsent(final K key, final Function<? super K, ? extends V> mappingFunction) {
|
||||
this.purgeStale();
|
||||
final Reference<V> vReference = this.raw.computeIfAbsent(wrapKey(key),
|
||||
final Ref<V> vReference = this.raw.computeIfAbsent(wrapKey(key),
|
||||
kReference -> wrapValue(mappingFunction.apply(unwrap(kReference))));
|
||||
return unwrap(vReference);
|
||||
}
|
||||
@ -144,7 +145,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public V computeIfPresent(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
this.purgeStale();
|
||||
final Reference<V> vReference = this.raw.computeIfPresent(wrapKey(key),
|
||||
final Ref<V> vReference = this.raw.computeIfPresent(wrapKey(key),
|
||||
(kReference, vReference1) -> wrapValue(remappingFunction.apply(unwrap(kReference), unwrap(vReference1))));
|
||||
return unwrap(vReference);
|
||||
}
|
||||
@ -173,11 +174,11 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
this.purgeStale();
|
||||
final Set<Reference<K>> referenceSet = this.raw.keySet();
|
||||
final Set<Ref<K>> referenceSet = this.raw.keySet();
|
||||
return new AbstractSet<K>() {
|
||||
@Override
|
||||
public Iterator<K> iterator() {
|
||||
final Iterator<Reference<K>> referenceIter = referenceSet.iterator();
|
||||
final Iterator<Ref<K>> referenceIter = referenceSet.iterator();
|
||||
return new Iterator<K>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
@ -201,11 +202,11 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
this.purgeStale();
|
||||
final Collection<Reference<V>> referenceValues = this.raw.values();
|
||||
final Collection<Ref<V>> referenceValues = this.raw.values();
|
||||
return new AbstractCollection<V>() {
|
||||
@Override
|
||||
public Iterator<V> iterator() {
|
||||
final Iterator<Reference<V>> referenceIter = referenceValues.iterator();
|
||||
final Iterator<Ref<V>> referenceIter = referenceValues.iterator();
|
||||
return new Iterator<V>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
@ -229,11 +230,11 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
this.purgeStale();
|
||||
final Set<Entry<Reference<K>, Reference<V>>> referenceEntrySet = this.raw.entrySet();
|
||||
final Set<Entry<Ref<K>, Ref<V>>> referenceEntrySet = this.raw.entrySet();
|
||||
return new AbstractSet<Entry<K, V>>() {
|
||||
@Override
|
||||
public Iterator<Entry<K, V>> iterator() {
|
||||
final Iterator<Entry<Reference<K>, Reference<V>>> referenceIter = referenceEntrySet.iterator();
|
||||
final Iterator<Entry<Ref<K>, Ref<V>>> referenceIter = referenceEntrySet.iterator();
|
||||
return new Iterator<Entry<K, V>>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
@ -242,7 +243,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
|
||||
@Override
|
||||
public Entry<K, V> next() {
|
||||
final Entry<Reference<K>, Reference<V>> next = referenceIter.next();
|
||||
final Entry<Ref<K>, Ref<V>> next = referenceIter.next();
|
||||
return new Entry<K, V>() {
|
||||
@Override
|
||||
public K getKey() {
|
||||
@ -300,11 +301,11 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void purgeStale() {
|
||||
Reference<? extends K> key;
|
||||
Reference<? extends V> value;
|
||||
Ref<? extends K> key;
|
||||
Ref<? extends V> value;
|
||||
|
||||
// 清除无效key对应键值对
|
||||
while ((key = this.lastKeyQueue.poll()) != null) {
|
||||
while ((key = (Ref<? extends K>) this.lastKeyQueue.poll()) != null) {
|
||||
value = this.raw.remove(key);
|
||||
if (null != purgeListener) {
|
||||
purgeListener.accept(key, value);
|
||||
@ -312,8 +313,8 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
}
|
||||
|
||||
// 清除无效value对应的键值对
|
||||
while ((value = this.lastValueQueue.poll()) != null) {
|
||||
MapUtil.removeByValue(this.raw, (Reference<V>) value);
|
||||
while ((value = (Ref<? extends V>) this.lastValueQueue.poll()) != null) {
|
||||
MapUtil.removeByValue(this.raw, (Ref<V>) value);
|
||||
if (null != purgeListener) {
|
||||
purgeListener.accept(null, value);
|
||||
}
|
||||
@ -327,7 +328,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
* @param queue {@link ReferenceQueue}
|
||||
* @return {@link Reference}
|
||||
*/
|
||||
abstract Reference<K> wrapKey(final K key, final ReferenceQueue<? super K> queue);
|
||||
abstract Ref<K> wrapKey(final K key, final ReferenceQueue<? super K> queue);
|
||||
|
||||
/**
|
||||
* 根据Reference类型构建value对应的{@link Reference}
|
||||
@ -336,7 +337,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
* @param queue {@link ReferenceQueue}
|
||||
* @return {@link Reference}
|
||||
*/
|
||||
abstract Reference<V> wrapValue(final V value, final ReferenceQueue<? super V> queue);
|
||||
abstract Ref<V> wrapValue(final V value, final ReferenceQueue<? super V> queue);
|
||||
|
||||
/**
|
||||
* 根据Reference类型构建key对应的{@link Reference}
|
||||
@ -345,7 +346,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
* @return {@link Reference}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Reference<K> wrapKey(final Object key) {
|
||||
private Ref<K> wrapKey(final Object key) {
|
||||
return wrapKey((K) key, this.lastKeyQueue);
|
||||
}
|
||||
|
||||
@ -356,7 +357,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
* @return {@link Reference}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Reference<V> wrapValue(final Object value) {
|
||||
private Ref<V> wrapValue(final Object value) {
|
||||
return wrapValue((V) value, this.lastValueQueue);
|
||||
}
|
||||
|
||||
@ -367,7 +368,7 @@ public abstract class ReferenceConcurrentMap<K, V> implements ConcurrentMap<K, V
|
||||
* @param obj 对象
|
||||
* @return 值
|
||||
*/
|
||||
private static <T> T unwrap(final Reference<T> obj) {
|
||||
private static <T> T unwrap(final Ref<T> obj) {
|
||||
return ReferenceUtil.get(obj);
|
||||
}
|
||||
}
|
||||
|
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.map.reference;
|
||||
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.lang.ref.ReferenceType;
|
||||
import org.dromara.hutool.core.lang.ref.SoftObj;
|
||||
import org.dromara.hutool.core.lang.ref.WeakObj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 线程安全的ReferenceMap实现<br>
|
||||
* 参考:jdk.management.resource.internal.WeakKeyConcurrentHashMap
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @author looly
|
||||
*/
|
||||
public class ReferenceKeyConcurrentMap<K, V> implements ConcurrentMap<K, V>, Iterable<Map.Entry<K, V>>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final ConcurrentMap<Reference<K>, V> raw;
|
||||
private final ReferenceQueue<K> lastQueue;
|
||||
private final ReferenceType keyType;
|
||||
/**
|
||||
* 回收监听
|
||||
*/
|
||||
private BiConsumer<Reference<? extends K>, V> purgeListener;
|
||||
|
||||
// region 构造
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param raw {@link ConcurrentMap}实现
|
||||
* @param referenceType Reference类型
|
||||
*/
|
||||
public ReferenceKeyConcurrentMap(final ConcurrentMap<Reference<K>, V> raw, final ReferenceType referenceType) {
|
||||
this.raw = raw;
|
||||
this.keyType = referenceType;
|
||||
lastQueue = new ReferenceQueue<>();
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 设置对象回收清除监听
|
||||
*
|
||||
* @param purgeListener 监听函数
|
||||
*/
|
||||
public void setPurgeListener(final BiConsumer<Reference<? extends K>, V> purgeListener) {
|
||||
this.purgeListener = purgeListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return 0 == size();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public V get(final Object key) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.get(ofKey((K) key, null));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean containsKey(final Object key) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.containsKey(ofKey((K) key, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(final Object value) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(final K key, final V value) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.put(ofKey(key, this.lastQueue), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V putIfAbsent(final K key, final V value) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.putIfAbsent(ofKey(key, this.lastQueue), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(final Map<? extends K, ? extends V> m) {
|
||||
m.forEach(this::put);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V replace(final K key, final V value) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.replace(ofKey(key, this.lastQueue), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replace(final K key, final V oldValue, final V newValue) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.replace(ofKey(key, this.lastQueue), oldValue, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(final BiFunction<? super K, ? super V, ? extends V> function) {
|
||||
this.purgeStaleKeys();
|
||||
this.raw.replaceAll((kWeakKey, value) -> function.apply(kWeakKey.get(), value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V computeIfAbsent(final K key, final Function<? super K, ? extends V> mappingFunction) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.computeIfAbsent(ofKey(key, this.lastQueue), kWeakKey -> mappingFunction.apply(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V computeIfPresent(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.computeIfPresent(ofKey(key, this.lastQueue), (kWeakKey, value) -> remappingFunction.apply(key, value));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public V remove(final Object key) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.remove(ofKey((K) key, null));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean remove(final Object key, final Object value) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.remove(ofKey((K) key, null), value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
@Override
|
||||
public void clear() {
|
||||
this.raw.clear();
|
||||
while (lastQueue.poll() != null) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
this.purgeStaleKeys();
|
||||
// TODO 非高效方式的set转换,应该返回一个view
|
||||
final Collection<K> trans = CollUtil.trans(this.raw.keySet(), (reference) -> null == reference ? null : reference.get());
|
||||
return new HashSet<>(trans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.entrySet().stream()
|
||||
.map(entry -> new AbstractMap.SimpleImmutableEntry<>(entry.getKey().get(), entry.getValue()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(final BiConsumer<? super K, ? super V> action) {
|
||||
this.purgeStaleKeys();
|
||||
this.raw.forEach((key, value)-> action.accept(key.get(), value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<K, V>> iterator() {
|
||||
return entrySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V compute(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.compute(ofKey(key, this.lastQueue), (kWeakKey, value) -> remappingFunction.apply(key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V merge(final K key, final V value, final BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
||||
this.purgeStaleKeys();
|
||||
return this.raw.merge(ofKey(key, this.lastQueue), value, remappingFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除被回收的键
|
||||
*/
|
||||
private void purgeStaleKeys() {
|
||||
Reference<? extends K> reference;
|
||||
V value;
|
||||
while ((reference = this.lastQueue.poll()) != null) {
|
||||
value = this.raw.remove(reference);
|
||||
if (null != purgeListener) {
|
||||
purgeListener.accept(reference, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Reference类型构建key对应的{@link Reference}
|
||||
*
|
||||
* @param key 键
|
||||
* @param queue {@link ReferenceQueue}
|
||||
* @return {@link Reference}
|
||||
*/
|
||||
private Reference<K> ofKey(final K key, final ReferenceQueue<? super K> queue) {
|
||||
switch (keyType) {
|
||||
case WEAK:
|
||||
return new WeakObj<>(key, queue);
|
||||
case SOFT:
|
||||
return new SoftObj<>(key, queue);
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported key type: " + keyType);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2024. looly(loolly@aliyun.com)
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
@ -12,27 +12,29 @@
|
||||
|
||||
package org.dromara.hutool.core.map.reference;
|
||||
|
||||
import org.dromara.hutool.core.lang.ref.ReferenceType;
|
||||
import org.dromara.hutool.core.lang.ref.Ref;
|
||||
import org.dromara.hutool.core.lang.ref.SoftObj;
|
||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* 线程安全的SoftMap实现<br>
|
||||
* 键和值都为Soft引用,即,在GC报告内存不足时会被GC回收
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SoftKeyConcurrentMap<K, V> extends ReferenceKeyConcurrentMap<K, V> {
|
||||
public class SoftConcurrentMap<K, V> extends ReferenceConcurrentMap<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public SoftKeyConcurrentMap() {
|
||||
public SoftConcurrentMap() {
|
||||
this(new SafeConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
@ -41,7 +43,17 @@ public class SoftKeyConcurrentMap<K, V> extends ReferenceKeyConcurrentMap<K, V>
|
||||
*
|
||||
* @param raw {@link ConcurrentMap}实现
|
||||
*/
|
||||
public SoftKeyConcurrentMap(final ConcurrentMap<Reference<K>, V> raw) {
|
||||
super(raw, ReferenceType.SOFT);
|
||||
public SoftConcurrentMap(final ConcurrentMap<Ref<K>, Ref<V>> raw) {
|
||||
super(raw);
|
||||
}
|
||||
|
||||
@Override
|
||||
Ref<K> wrapKey(final K key, final ReferenceQueue<? super K> queue) {
|
||||
return new SoftObj<>(key, queue);
|
||||
}
|
||||
|
||||
@Override
|
||||
Ref<V> wrapValue(final V value, final ReferenceQueue<? super V> queue) {
|
||||
return new SoftObj<>(value, queue);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2024. looly(loolly@aliyun.com)
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
@ -12,28 +12,29 @@
|
||||
|
||||
package org.dromara.hutool.core.map.reference;
|
||||
|
||||
import org.dromara.hutool.core.lang.ref.ReferenceType;
|
||||
import org.dromara.hutool.core.lang.ref.Ref;
|
||||
import org.dromara.hutool.core.lang.ref.WeakObj;
|
||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* 线程安全的WeakMap实现<br>
|
||||
* 参考:jdk.management.resource.internal.WeakKeyConcurrentHashMap
|
||||
* 键和值都为Weak引用,即,在GC时发现弱引用会回收其对象
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @author looly
|
||||
* @since 5.8.0
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class WeakKeyConcurrentMap<K, V> extends ReferenceKeyConcurrentMap<K, V> {
|
||||
public class WeakConcurrentMap<K, V> extends ReferenceConcurrentMap<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public WeakKeyConcurrentMap() {
|
||||
public WeakConcurrentMap() {
|
||||
this(new SafeConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
@ -42,7 +43,17 @@ public class WeakKeyConcurrentMap<K, V> extends ReferenceKeyConcurrentMap<K, V>
|
||||
*
|
||||
* @param raw {@link ConcurrentMap}实现
|
||||
*/
|
||||
public WeakKeyConcurrentMap(final ConcurrentMap<Reference<K>, V> raw) {
|
||||
super(raw, ReferenceType.WEAK);
|
||||
public WeakConcurrentMap(final ConcurrentMap<Ref<K>, Ref<V>> raw) {
|
||||
super(raw);
|
||||
}
|
||||
|
||||
@Override
|
||||
Ref<K> wrapKey(final K key, final ReferenceQueue<? super K> queue) {
|
||||
return new WeakObj<>(key, queue);
|
||||
}
|
||||
|
||||
@Override
|
||||
Ref<V> wrapValue(final V value, final ReferenceQueue<? super V> queue) {
|
||||
return new WeakObj<>(value, queue);
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.core.reflect;
|
||||
|
||||
import org.dromara.hutool.core.convert.Convert;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@ -29,7 +29,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class ActualTypeMapperPool {
|
||||
|
||||
private static final WeakKeyConcurrentMap<Type, Map<Type, Type>> CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Type, Map<Type, Type>> CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 获取泛型变量和泛型实际类型的对应关系Map
|
||||
|
@ -14,7 +14,7 @@ package org.dromara.hutool.core.reflect;
|
||||
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.creator.DefaultObjectCreator;
|
||||
import org.dromara.hutool.core.reflect.creator.PossibleObjectCreator;
|
||||
|
||||
@ -29,7 +29,7 @@ public class ConstructorUtil {
|
||||
/**
|
||||
* 构造对象缓存
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Constructor<?>[]> CONSTRUCTORS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Constructor<?>[]> CONSTRUCTORS_CACHE = new WeakConcurrentMap<>();
|
||||
// --------------------------------------------------------------------------------------------------------- Constructor
|
||||
|
||||
/**
|
||||
|
@ -13,13 +13,13 @@
|
||||
package org.dromara.hutool.core.reflect;
|
||||
|
||||
import org.dromara.hutool.core.annotation.Alias;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.convert.Convert;
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
@ -36,7 +36,7 @@ public class FieldUtil {
|
||||
/**
|
||||
* 字段缓存
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Field[]> FIELDS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Field[]> FIELDS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------- Field
|
||||
|
||||
|
@ -16,7 +16,7 @@ import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.lang.mutable.Mutable;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableObj;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@ -63,7 +63,7 @@ import java.util.function.Predicate;
|
||||
* <p><strong>缓存</strong>
|
||||
* <p>对于{@link #getDeclaredMethods}与{@link #getMethods}方法与基于这两个方法实现的,
|
||||
* 所有{@code xxxFromMethods}与{@code xxxFromDeclaredMethods}方法,
|
||||
* 都提供了缓存基于{@link WeakKeyConcurrentMap}的缓存支持。<br>
|
||||
* 都提供了缓存基于{@link WeakConcurrentMap}的缓存支持。<br>
|
||||
* {@link #getAllMethods}与所有{@code xxxFromAllMethods}方法都基于{@link #getDeclaredMethods}实现,
|
||||
* 但是每次全量查找,都需要重新遍历类层级结构,因此会带来一定的额外的性能损耗。<br>
|
||||
* 缓存在GC时会被回收,但是也可以通过{@link #clearCaches}手动清除缓存。
|
||||
@ -87,12 +87,12 @@ public class MethodScanner {
|
||||
/**
|
||||
* 方法缓存
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 直接声明的方法缓存
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Method[]> DECLARED_METHODS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Method[]> DECLARED_METHODS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
// region ============= basic =============
|
||||
|
||||
|
@ -22,7 +22,7 @@ import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.ModifierUtil;
|
||||
@ -44,11 +44,11 @@ public class MethodUtil {
|
||||
/**
|
||||
* 方法缓存
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakConcurrentMap<>();
|
||||
/**
|
||||
* 直接声明的方法缓存
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<Class<?>, Method[]> DECLARED_METHODS_CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Class<?>, Method[]> DECLARED_METHODS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------- method
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
package org.dromara.hutool.core.regex;
|
||||
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -209,7 +209,7 @@ public class PatternPool {
|
||||
/**
|
||||
* Pattern池
|
||||
*/
|
||||
private static final WeakKeyConcurrentMap<RegexWithFlag, Pattern> POOL = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<RegexWithFlag, Pattern> POOL = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 先从Pattern池中查找正则对应的{@link Pattern},找不到则编译正则表达式并入池。
|
||||
|
@ -14,7 +14,7 @@ package org.dromara.hutool.core.text.placeholder;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.lang.mutable.MutableEntry;
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.text.placeholder.template.NamedPlaceholderStrTemplate;
|
||||
import org.dromara.hutool.core.text.placeholder.template.SinglePlaceholderStrTemplate;
|
||||
@ -27,7 +27,7 @@ import java.util.Map;
|
||||
* @author Looly
|
||||
*/
|
||||
public class StrFormatter {
|
||||
private static final WeakKeyConcurrentMap<Map.Entry<CharSequence, Object>, StrTemplate> CACHE = new WeakKeyConcurrentMap<>();
|
||||
private static final WeakConcurrentMap<Map.Entry<CharSequence, Object>, StrTemplate> CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 格式化字符串<br>
|
||||
|
@ -339,7 +339,7 @@ public class ObjUtil {
|
||||
* @return 映射函数的结果, 如果输入对象为 null,则返回 null
|
||||
*/
|
||||
public static <T, R> R apply(final T source, final Function<T, R> handler) {
|
||||
return defaultIfNull(source, handler, null);
|
||||
return defaultIfNull(source, handler, (R)null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
package org.dromara.hutool.core.map;
|
||||
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.thread.ConcurrencyTester;
|
||||
import org.dromara.hutool.core.thread.ThreadUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
@ -24,9 +24,8 @@ public class WeakConcurrentMapTest {
|
||||
|
||||
@Test
|
||||
public void putAndGetTest() {
|
||||
final WeakKeyConcurrentMap<Object, Object> map = new WeakKeyConcurrentMap<>();
|
||||
Object
|
||||
key1 = new Object();
|
||||
final WeakConcurrentMap<Object, Object> map = new WeakConcurrentMap<>();
|
||||
Object key1 = new Object();
|
||||
final Object value1 = new Object();
|
||||
Object key2 = new Object();
|
||||
final Object value2 = new Object();
|
||||
@ -58,7 +57,7 @@ public class WeakConcurrentMapTest {
|
||||
|
||||
@Test
|
||||
public void getConcurrencyTest() {
|
||||
final WeakKeyConcurrentMap<String, String> cache = new WeakKeyConcurrentMap<>();
|
||||
final WeakConcurrentMap<String, String> cache = new WeakConcurrentMap<>();
|
||||
final ConcurrencyTester tester = new ConcurrencyTester(2000);
|
||||
tester.test(() -> cache.computeIfAbsent("aaa" + RandomUtil.randomInt(2), (key) -> "aaaValue"));
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
package org.dromara.hutool.extra.spring.cglib;
|
||||
|
||||
import org.dromara.hutool.core.map.reference.WeakKeyConcurrentMap;
|
||||
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.springframework.cglib.beans.BeanCopier;
|
||||
import org.springframework.cglib.core.Converter;
|
||||
@ -30,7 +30,7 @@ public enum BeanCopierCache {
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private final WeakKeyConcurrentMap<String, BeanCopier> cache = new WeakKeyConcurrentMap<>();
|
||||
private final WeakConcurrentMap<String, BeanCopier> cache = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素
|
||||
|
Loading…
x
Reference in New Issue
Block a user