diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index b66b15f0d..84e7c5917 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -225,8 +225,8 @@ public class BeanUtil { */ private static Map internalGetPropertyDescriptorMap(Class clazz, boolean ignoreCase) throws BeanException { final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz); - final Map map = ignoreCase ? new CaseInsensitiveMap<>(propertyDescriptors.length, 1) - : new HashMap<>((int) (propertyDescriptors.length), 1); + final Map map = ignoreCase ? new CaseInsensitiveMap<>(propertyDescriptors.length, 1f) + : new HashMap<>(propertyDescriptors.length, 1); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { map.put(propertyDescriptor.getName(), propertyDescriptor); diff --git a/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseLinkedMap.java b/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseLinkedMap.java index fbd2b776c..639bfbfcc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseLinkedMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseLinkedMap.java @@ -1,7 +1,5 @@ package cn.hutool.core.map; -import cn.hutool.core.util.StrUtil; - import java.util.LinkedHashMap; import java.util.Map; @@ -15,7 +13,7 @@ import java.util.Map; * @param 值类型 * @since 4.0.7 */ -public class CamelCaseLinkedMap extends CustomKeyMap { +public class CamelCaseLinkedMap extends CamelCaseMap { private static final long serialVersionUID = 4043263744224569870L; // ------------------------------------------------------------------------- Constructor start @@ -48,7 +46,7 @@ public class CamelCaseLinkedMap extends CustomKeyMap { * 构造 * * @param loadFactor 加载因子 - * @param m Map + * @param m Map,数据会被默认拷贝到一个新的LinkedHashMap中 */ public CamelCaseLinkedMap(float loadFactor, Map m) { this(m.size(), loadFactor); @@ -65,18 +63,4 @@ public class CamelCaseLinkedMap extends CustomKeyMap { super(new LinkedHashMap<>(initialCapacity, loadFactor)); } // ------------------------------------------------------------------------- Constructor end - - /** - * 将Key转为驼峰风格,如果key为字符串的话 - * - * @param key KEY - * @return 驼峰Key - */ - @Override - protected Object customKey(Object key) { - if (key instanceof CharSequence) { - key = StrUtil.toCamelCase(key.toString()); - } - return key; - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseMap.java b/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseMap.java index ea1642d14..4759b7202 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/CamelCaseMap.java @@ -1,24 +1,24 @@ package cn.hutool.core.map; +import cn.hutool.core.util.StrUtil; + import java.util.HashMap; import java.util.Map; -import cn.hutool.core.util.StrUtil; - /** * 驼峰Key风格的Map
* 对KEY转换为驼峰,get("int_value")和get("intValue")获得的值相同,put进入的值也会被覆盖 * - * @author Looly - * * @param 键类型 * @param 值类型 + * @author Looly * @since 4.0.7 */ -public class CamelCaseMap extends CustomKeyMap { +public class CamelCaseMap extends FuncKeyMap { private static final long serialVersionUID = 4043263744224569870L; // ------------------------------------------------------------------------- Constructor start + /** * 构造 */ @@ -48,7 +48,7 @@ public class CamelCaseMap extends CustomKeyMap { * 构造 * * @param loadFactor 加载因子 - * @param m Map + * @param m 初始Map,数据会被默认拷贝到一个新的HashMap中 */ public CamelCaseMap(float loadFactor, Map m) { this(m.size(), loadFactor); @@ -59,24 +59,26 @@ public class CamelCaseMap extends CustomKeyMap { * 构造 * * @param initialCapacity 初始大小 - * @param loadFactor 加载因子 + * @param loadFactor 加载因子 */ public CamelCaseMap(int initialCapacity, float loadFactor) { - super(new HashMap<>(initialCapacity, loadFactor)); + this(MapBuilder.create(new HashMap<>(initialCapacity, loadFactor))); } - // ------------------------------------------------------------------------- Constructor end /** - * 将Key转为驼峰风格,如果key为字符串的话 + * 构造
+ * 注意此构造将传入的Map作为被包装的Map,针对任何修改,传入的Map都会被同样修改。 * - * @param key KEY - * @return 驼峰Key + * @param emptyMapBuilder Map构造器,必须构造空的Map */ - @Override - protected Object customKey(Object key) { - if (key instanceof CharSequence) { - key = StrUtil.toCamelCase(key.toString()); - } - return key; + CamelCaseMap(MapBuilder emptyMapBuilder) { + super(emptyMapBuilder.build(), (key) -> { + if (key instanceof CharSequence) { + key = StrUtil.toCamelCase(key.toString()); + } + //noinspection unchecked + return (K) key; + }); } + // ------------------------------------------------------------------------- Constructor end } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveLinkedMap.java b/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveLinkedMap.java index 51cdd2561..5be588ef3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveLinkedMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveLinkedMap.java @@ -13,7 +13,7 @@ import java.util.Map; * @param 值类型 * @since 3.3.1 */ -public class CaseInsensitiveLinkedMap extends CustomKeyMap { +public class CaseInsensitiveLinkedMap extends CaseInsensitiveMap { private static final long serialVersionUID = 4043263744224569870L; // ------------------------------------------------------------------------- Constructor start @@ -64,18 +64,4 @@ public class CaseInsensitiveLinkedMap extends CustomKeyMap { super(new LinkedHashMap<>(initialCapacity, loadFactor)); } // ------------------------------------------------------------------------- Constructor end - - /** - * 将Key转为小写 - * - * @param key KEY - * @return 小写KEY - */ - @Override - protected Object customKey(Object key) { - if (key instanceof CharSequence) { - key = key.toString().toLowerCase(); - } - return key; - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveMap.java b/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveMap.java index 0c892b268..40f805ad0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveMap.java @@ -13,7 +13,7 @@ import java.util.Map; * @param 值类型 * @since 3.0.2 */ -public class CaseInsensitiveMap extends CustomKeyMap { +public class CaseInsensitiveMap extends FuncKeyMap { private static final long serialVersionUID = 4043263744224569870L; //------------------------------------------------------------------------- Constructor start @@ -34,9 +34,10 @@ public class CaseInsensitiveMap extends CustomKeyMap { } /** - * 构造 + * 构造
+ * 注意此构造将传入的Map作为被包装的Map,针对任何修改,传入的Map都会被同样修改。 * - * @param m Map + * @param m 被包装的自定义Map创建器 */ public CaseInsensitiveMap(Map m) { this(DEFAULT_LOAD_FACTOR, m); @@ -61,21 +62,23 @@ public class CaseInsensitiveMap extends CustomKeyMap { * @param loadFactor 加载因子 */ public CaseInsensitiveMap(int initialCapacity, float loadFactor) { - super(new HashMap<>(initialCapacity, loadFactor)); + this(MapBuilder.create(new HashMap<>(initialCapacity, loadFactor))); } - //------------------------------------------------------------------------- Constructor end /** - * 将Key转为小写 + * 构造
+ * 注意此构造将传入的Map作为被包装的Map,针对任何修改,传入的Map都会被同样修改。 * - * @param key KEY - * @return 小写KEY + * @param emptyMapBuilder 被包装的自定义Map创建器 */ - @Override - protected Object customKey(Object key) { - if (key instanceof CharSequence) { - key = key.toString().toLowerCase(); - } - return key; + CaseInsensitiveMap(MapBuilder emptyMapBuilder) { + super(emptyMapBuilder.build(), (key)->{ + if (key instanceof CharSequence) { + key = key.toString().toLowerCase(); + } + //noinspection unchecked + return (K) key; + }); } + //------------------------------------------------------------------------- Constructor end } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveTreeMap.java b/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveTreeMap.java index 7f8b065f6..69f3ec538 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveTreeMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/CaseInsensitiveTreeMap.java @@ -15,7 +15,7 @@ import java.util.TreeMap; * @param 值类型 * @since 3.3.1 */ -public class CaseInsensitiveTreeMap extends CustomKeyMap { +public class CaseInsensitiveTreeMap extends CaseInsensitiveMap { private static final long serialVersionUID = 4043263744224569870L; // ------------------------------------------------------------------------- Constructor start @@ -40,7 +40,7 @@ public class CaseInsensitiveTreeMap extends CustomKeyMap { /** * 构造 * - * @param m Map + * @param m Map,初始Map,键值对会被复制到新的TreeMap中 * @since 3.1.2 */ public CaseInsensitiveTreeMap(SortedMap m) { @@ -56,18 +56,4 @@ public class CaseInsensitiveTreeMap extends CustomKeyMap { super(new TreeMap<>(comparator)); } // ------------------------------------------------------------------------- Constructor end - - /** - * 将Key转为小写 - * - * @param key KEY - * @return 小写KEY - */ - @Override - protected Object customKey(Object key) { - if (key instanceof CharSequence) { - key = key.toString().toLowerCase(); - } - return key; - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/CustomKeyMap.java b/hutool-core/src/main/java/cn/hutool/core/map/CustomKeyMap.java index 4584943a5..04ed9d371 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/CustomKeyMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/CustomKeyMap.java @@ -18,11 +18,11 @@ public abstract class CustomKeyMap extends MapWrapper { * 构造
* 通过传入一个Map从而确定Map的类型,子类需创建一个空的Map,而非传入一个已有Map,否则值可能会被修改 * - * @param m Map 被包装的Map + * @param emptyMap Map 被包装的Map,必须为空Map,否则自定义key会无效 * @since 3.1.2 */ - public CustomKeyMap(Map m) { - super(m); + public CustomKeyMap(Map emptyMap) { + super(emptyMap); } @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java b/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java index 1559fde7a..5ddaaa6f9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java @@ -3,7 +3,8 @@ package cn.hutool.core.map; import java.util.LinkedHashMap; /** - * 固定大小的{@link LinkedHashMap} 实现 + * 固定大小的{@link LinkedHashMap} 实现
+ * 注意此类非线程安全,由于{@link #get(Object)}操作会修改链表的顺序结构,因此也不可以使用读写锁。 * * @author looly * diff --git a/hutool-core/src/main/java/cn/hutool/core/map/FuncKeyMap.java b/hutool-core/src/main/java/cn/hutool/core/map/FuncKeyMap.java index e5ca6a719..0cc468d61 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/FuncKeyMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/FuncKeyMap.java @@ -19,13 +19,14 @@ public class FuncKeyMap extends CustomKeyMap { // ------------------------------------------------------------------------- Constructor start /** - * 构造 + * 构造
+ * 注意提供的Map中不能有键值对,否则可能导致自定义key失效 * - * @param m Map + * @param emptyMap Map,提供的空map * @param keyFunc 自定义KEY的函数 */ - public FuncKeyMap(Map m, Function keyFunc) { - super(m); + public FuncKeyMap(Map emptyMap, Function keyFunc) { + super(emptyMap); this.keyFunc = keyFunc; } // ------------------------------------------------------------------------- Constructor end diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapBuilder.java b/hutool-core/src/main/java/cn/hutool/core/map/MapBuilder.java index 5840d9204..2f605d71e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/MapBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/MapBuilder.java @@ -13,7 +13,7 @@ import java.util.function.Supplier; * @param Value类型 * @since 3.1.1 */ -public class MapBuilder implements Builder> { +public class MapBuilder implements Builder> { private static final long serialVersionUID = 1L; private final Map map; @@ -120,6 +120,17 @@ public class MapBuilder implements Builder> { return this; } + /** + * 清空Map + * + * @return this + * @since 5.7.23 + */ + public MapBuilder clear() { + this.map.clear(); + return this; + } + /** * 创建后的map * diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapWrapper.java b/hutool-core/src/main/java/cn/hutool/core/map/MapWrapper.java index bfd81dd86..3c1ac5936 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/MapWrapper.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/MapWrapper.java @@ -88,7 +88,6 @@ public class MapWrapper implements Map, Iterable>, S } @Override - @SuppressWarnings("NullableProblems") public void putAll(Map m) { raw.putAll(m); } @@ -99,25 +98,21 @@ public class MapWrapper implements Map, Iterable>, S } @Override - @SuppressWarnings("NullableProblems") public Collection values() { return raw.values(); } @Override - @SuppressWarnings("NullableProblems") public Set keySet() { return raw.keySet(); } @Override - @SuppressWarnings("NullableProblems") public Set> entrySet() { return raw.entrySet(); } @Override - @SuppressWarnings("NullableProblems") public Iterator> iterator() { return this.entrySet().iterator(); } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index a01dc608b..f31190313 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.ValueProvider; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.map.MapBuilder; import cn.hutool.core.map.MapUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.ArrayUtil; @@ -78,14 +79,15 @@ public class BeanUtilTest { @Test public void fillBeanWithMapIgnoreCaseTest() { - HashMap map = MapUtil.newHashMap(); - map.put("Name", "Joe"); - map.put("aGe", 12); - map.put("openId", "DFDFSDFWERWER"); + Map map = MapBuilder.create() + .put("Name", "Joe") + .put("aGe", 12) + .put("openId", "DFDFSDFWERWER") + .build(); SubPerson person = BeanUtil.fillBeanWithMapIgnoreCase(map, new SubPerson(), false); - Assert.assertEquals(person.getName(), "Joe"); - Assert.assertEquals(person.getAge(), 12); - Assert.assertEquals(person.getOpenid(), "DFDFSDFWERWER"); + Assert.assertEquals("Joe", person.getName()); + Assert.assertEquals(12, person.getAge()); + Assert.assertEquals("DFDFSDFWERWER", person.getOpenid()); } @Test