This commit is contained in:
Looly 2022-03-06 21:01:08 +08:00
parent 4b22f7cc74
commit 1e113ef83f
12 changed files with 75 additions and 104 deletions

View File

@ -225,8 +225,8 @@ public class BeanUtil {
*/
private static Map<String, PropertyDescriptor> internalGetPropertyDescriptorMap(Class<?> clazz, boolean ignoreCase) throws BeanException {
final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
final Map<String, PropertyDescriptor> map = ignoreCase ? new CaseInsensitiveMap<>(propertyDescriptors.length, 1)
: new HashMap<>((int) (propertyDescriptors.length), 1);
final Map<String, PropertyDescriptor> map = ignoreCase ? new CaseInsensitiveMap<>(propertyDescriptors.length, 1f)
: new HashMap<>(propertyDescriptors.length, 1);
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
map.put(propertyDescriptor.getName(), propertyDescriptor);

View File

@ -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 <V> 值类型
* @since 4.0.7
*/
public class CamelCaseLinkedMap<K, V> extends CustomKeyMap<K, V> {
public class CamelCaseLinkedMap<K, V> extends CamelCaseMap<K, V> {
private static final long serialVersionUID = 4043263744224569870L;
// ------------------------------------------------------------------------- Constructor start
@ -48,7 +46,7 @@ public class CamelCaseLinkedMap<K, V> extends CustomKeyMap<K, V> {
* 构造
*
* @param loadFactor 加载因子
* @param m Map
* @param m Map数据会被默认拷贝到一个新的LinkedHashMap中
*/
public CamelCaseLinkedMap(float loadFactor, Map<? extends K, ? extends V> m) {
this(m.size(), loadFactor);
@ -65,18 +63,4 @@ public class CamelCaseLinkedMap<K, V> extends CustomKeyMap<K, V> {
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;
}
}

View File

@ -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<br>
* 对KEY转换为驼峰get("int_value")和get("intValue")获得的值相同put进入的值也会被覆盖
*
* @author Looly
*
* @param <K> 键类型
* @param <V> 值类型
* @author Looly
* @since 4.0.7
*/
public class CamelCaseMap<K, V> extends CustomKeyMap<K, V> {
public class CamelCaseMap<K, V> extends FuncKeyMap<K, V> {
private static final long serialVersionUID = 4043263744224569870L;
// ------------------------------------------------------------------------- Constructor start
/**
* 构造
*/
@ -48,7 +48,7 @@ public class CamelCaseMap<K, V> extends CustomKeyMap<K, V> {
* 构造
*
* @param loadFactor 加载因子
* @param m Map
* @param m 初始Map数据会被默认拷贝到一个新的HashMap中
*/
public CamelCaseMap(float loadFactor, Map<? extends K, ? extends V> m) {
this(m.size(), loadFactor);
@ -59,24 +59,26 @@ public class CamelCaseMap<K, V> extends CustomKeyMap<K, V> {
* 构造
*
* @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为字符串的话
* 构造<br>
* 注意此构造将传入的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<K, V> emptyMapBuilder) {
super(emptyMapBuilder.build(), (key) -> {
if (key instanceof CharSequence) {
key = StrUtil.toCamelCase(key.toString());
}
//noinspection unchecked
return (K) key;
});
}
// ------------------------------------------------------------------------- Constructor end
}

View File

@ -13,7 +13,7 @@ import java.util.Map;
* @param <V> 值类型
* @since 3.3.1
*/
public class CaseInsensitiveLinkedMap<K, V> extends CustomKeyMap<K, V> {
public class CaseInsensitiveLinkedMap<K, V> extends CaseInsensitiveMap<K, V> {
private static final long serialVersionUID = 4043263744224569870L;
// ------------------------------------------------------------------------- Constructor start
@ -64,18 +64,4 @@ public class CaseInsensitiveLinkedMap<K, V> extends CustomKeyMap<K, V> {
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;
}
}

View File

@ -13,7 +13,7 @@ import java.util.Map;
* @param <V> 值类型
* @since 3.0.2
*/
public class CaseInsensitiveMap<K, V> extends CustomKeyMap<K, V> {
public class CaseInsensitiveMap<K, V> extends FuncKeyMap<K, V> {
private static final long serialVersionUID = 4043263744224569870L;
//------------------------------------------------------------------------- Constructor start
@ -34,9 +34,10 @@ public class CaseInsensitiveMap<K, V> extends CustomKeyMap<K, V> {
}
/**
* 构造
* 构造<br>
* 注意此构造将传入的Map作为被包装的Map针对任何修改传入的Map都会被同样修改
*
* @param m Map
* @param m 被包装的自定义Map创建器
*/
public CaseInsensitiveMap(Map<? extends K, ? extends V> m) {
this(DEFAULT_LOAD_FACTOR, m);
@ -61,21 +62,23 @@ public class CaseInsensitiveMap<K, V> extends CustomKeyMap<K, V> {
* @param loadFactor 加载因子
*/
public CaseInsensitiveMap(int initialCapacity, float loadFactor) {
super(new HashMap<>(initialCapacity, loadFactor));
this(MapBuilder.create(new HashMap<>(initialCapacity, loadFactor)));
}
//------------------------------------------------------------------------- Constructor end
/**
* 将Key转为小写
* 构造<br>
* 注意此构造将传入的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<K, V> emptyMapBuilder) {
super(emptyMapBuilder.build(), (key)->{
if (key instanceof CharSequence) {
key = key.toString().toLowerCase();
}
//noinspection unchecked
return (K) key;
});
}
//------------------------------------------------------------------------- Constructor end
}

View File

@ -15,7 +15,7 @@ import java.util.TreeMap;
* @param <V> 值类型
* @since 3.3.1
*/
public class CaseInsensitiveTreeMap<K, V> extends CustomKeyMap<K, V> {
public class CaseInsensitiveTreeMap<K, V> extends CaseInsensitiveMap<K, V> {
private static final long serialVersionUID = 4043263744224569870L;
// ------------------------------------------------------------------------- Constructor start
@ -40,7 +40,7 @@ public class CaseInsensitiveTreeMap<K, V> extends CustomKeyMap<K, V> {
/**
* 构造
*
* @param m Map
* @param m Map初始Map键值对会被复制到新的TreeMap中
* @since 3.1.2
*/
public CaseInsensitiveTreeMap(SortedMap<? extends K, ? extends V> m) {
@ -56,18 +56,4 @@ public class CaseInsensitiveTreeMap<K, V> extends CustomKeyMap<K, V> {
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;
}
}

View File

@ -18,11 +18,11 @@ public abstract class CustomKeyMap<K, V> extends MapWrapper<K, V> {
* 构造<br>
* 通过传入一个Map从而确定Map的类型子类需创建一个空的Map而非传入一个已有Map否则值可能会被修改
*
* @param m Map 被包装的Map
* @param emptyMap Map 被包装的Map必须为空Map否则自定义key会无效
* @since 3.1.2
*/
public CustomKeyMap(Map<K, V> m) {
super(m);
public CustomKeyMap(Map<K, V> emptyMap) {
super(emptyMap);
}
@Override

View File

@ -3,7 +3,8 @@ package cn.hutool.core.map;
import java.util.LinkedHashMap;
/**
* 固定大小的{@link LinkedHashMap} 实现
* 固定大小的{@link LinkedHashMap} 实现<br>
* 注意此类非线程安全由于{@link #get(Object)}操作会修改链表的顺序结构因此也不可以使用读写锁
*
* @author looly
*

View File

@ -19,13 +19,14 @@ public class FuncKeyMap<K, V> extends CustomKeyMap<K, V> {
// ------------------------------------------------------------------------- Constructor start
/**
* 构造
* 构造<br>
* 注意提供的Map中不能有键值对否则可能导致自定义key失效
*
* @param m Map
* @param emptyMap Map提供的空map
* @param keyFunc 自定义KEY的函数
*/
public FuncKeyMap(Map<K, V> m, Function<Object, K> keyFunc) {
super(m);
public FuncKeyMap(Map<K, V> emptyMap, Function<Object, K> keyFunc) {
super(emptyMap);
this.keyFunc = keyFunc;
}
// ------------------------------------------------------------------------- Constructor end

View File

@ -13,7 +13,7 @@ import java.util.function.Supplier;
* @param <V> Value类型
* @since 3.1.1
*/
public class MapBuilder<K, V> implements Builder<Map<K,V>> {
public class MapBuilder<K, V> implements Builder<Map<K, V>> {
private static final long serialVersionUID = 1L;
private final Map<K, V> map;
@ -120,6 +120,17 @@ public class MapBuilder<K, V> implements Builder<Map<K,V>> {
return this;
}
/**
* 清空Map
*
* @return this
* @since 5.7.23
*/
public MapBuilder<K, V> clear() {
this.map.clear();
return this;
}
/**
* 创建后的map
*

View File

@ -88,7 +88,6 @@ public class MapWrapper<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, S
}
@Override
@SuppressWarnings("NullableProblems")
public void putAll(Map<? extends K, ? extends V> m) {
raw.putAll(m);
}
@ -99,25 +98,21 @@ public class MapWrapper<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, S
}
@Override
@SuppressWarnings("NullableProblems")
public Collection<V> values() {
return raw.values();
}
@Override
@SuppressWarnings("NullableProblems")
public Set<K> keySet() {
return raw.keySet();
}
@Override
@SuppressWarnings("NullableProblems")
public Set<Entry<K, V>> entrySet() {
return raw.entrySet();
}
@Override
@SuppressWarnings("NullableProblems")
public Iterator<Entry<K, V>> iterator() {
return this.entrySet().iterator();
}

View File

@ -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<String, Object> map = MapUtil.newHashMap();
map.put("Name", "Joe");
map.put("aGe", 12);
map.put("openId", "DFDFSDFWERWER");
Map<String, Object> map = MapBuilder.<String, Object>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