This commit is contained in:
Looly 2022-05-12 00:58:38 +08:00
parent 1fa3450b27
commit 2841c1f484
3 changed files with 52 additions and 40 deletions

View File

@ -3,16 +3,19 @@
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
# 5.8.1.M1 (2022-05-10) # 5.8.1.M1 (2022-05-12)
### 🐣新特性 ### 🐣新特性
* 【core 】 BooleanUtil增加toBooleanObject方法issue#I56AG3@Gitee * 【core 】 BooleanUtil增加toBooleanObject方法issue#I56AG3@Gitee
* 【core 】 CharSequenceUtil增加startWithAnyIgnoreCase方法issue#2312@Github * 【core 】 CharSequenceUtil增加startWithAnyIgnoreCase方法issue#2312@Github
* 【system 】 JavaInfo增加版本issue#2310@Github * 【system 】 JavaInfo增加版本issue#2310@Github
*
### 🐞Bug修复 ### 🐞Bug修复
* 【core 】 MapUtil.map对null友好且修复了测试用例中分组问题pr#614@Gitee * 【core 】 MapUtil.map对null友好且修复了测试用例中分组问题pr#614@Gitee
* 【core 】 修复BeanUtil.beanToMap中properties为null的空指针问题issue#2303@Github * 【core 】 修复BeanUtil.beanToMap中properties为null的空指针问题issue#2303@Github
* 【db 】 DialectName中修正为POSTGRESQLissue#2308@Github * 【db 】 DialectName中修正为POSTGRESQLissue#2308@Github
* 【core 】 修复BeanPath无法识别引号内的内容问题issue#I56DE0@Gitee
* 【core 】 修复Map.entry方法返回可变不可变相反问题
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
@ -188,3 +191,6 @@
* 【json 】 JSON修复transient设置无效问题issue#2212@Github * 【json 】 JSON修复transient设置无效问题issue#2212@Github
* 【core 】 修复IterUtil.getElementType获取结果为null的问题issue#2222@Github * 【core 】 修复IterUtil.getElementType获取结果为null的问题issue#2222@Github
* 【core 】 修复农历转公历在闰月时错误issue#I4ZSGJ@Gitee * 【core 】 修复农历转公历在闰月时错误issue#I4ZSGJ@Gitee
# 5.7.x 或更早版本
* [https://gitee.com/dromara/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md](https://gitee.com/dromara/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md)

View File

@ -1,9 +1,9 @@
package cn.hutool.core.bean; package cn.hutool.core.bean;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
@ -11,7 +11,6 @@ import cn.hutool.core.util.StrUtil;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -68,7 +67,7 @@ public class BeanPath implements Serializable{
* @param expression 表达式 * @param expression 表达式
* @return BeanPath * @return BeanPath
*/ */
public static BeanPath create(String expression) { public static BeanPath create(final String expression) {
return new BeanPath(expression); return new BeanPath(expression);
} }
@ -77,17 +76,26 @@ public class BeanPath implements Serializable{
* *
* @param expression 表达式 * @param expression 表达式
*/ */
public BeanPath(String expression) { public BeanPath(final String expression) {
init(expression); init(expression);
} }
/**
* 获取表达式解析后的分段列表
*
* @return 表达式分段列表
*/
public List<String> getPatternParts(){
return this.patternParts;
}
/** /**
* 获取Bean中对应表达式的值 * 获取Bean中对应表达式的值
* *
* @param bean Bean对象或Map或List等 * @param bean Bean对象或Map或List等
* @return 如果对应值不存在则返回null * @return 如果对应值不存在则返回null
*/ */
public Object get(Object bean) { public Object get(final Object bean) {
return get(this.patternParts, bean, false); return get(this.patternParts, bean, false);
} }
@ -104,10 +112,16 @@ public class BeanPath implements Serializable{
* @param bean BeanMap或List * @param bean BeanMap或List
* @param value * @param value
*/ */
public void set(Object bean, Object value) { public void set(final Object bean, final Object value) {
set(bean, this.patternParts, value); set(bean, this.patternParts, value);
} }
@Override
public String toString() {
return this.patternParts.toString();
}
//region Private Methods
/** /**
* 设置表达式指定位置或filed对应的值<br> * 设置表达式指定位置或filed对应的值<br>
* 若表达式指向一个List则设置其坐标对应位置的值若指向Map则put对应key的值Bean则设置字段的值<br> * 若表达式指向一个List则设置其坐标对应位置的值若指向Map则put对应key的值Bean则设置字段的值<br>
@ -122,7 +136,7 @@ public class BeanPath implements Serializable{
* @param patternParts 表达式块列表 * @param patternParts 表达式块列表
* @param value * @param value
*/ */
private void set(Object bean, List<String> patternParts, Object value) { private void set(final Object bean, final List<String> patternParts, final Object value) {
Object subBean = get(patternParts, bean, true); Object subBean = get(patternParts, bean, true);
if(null == subBean) { if(null == subBean) {
set(bean, patternParts.subList(0, patternParts.size() - 1), new HashMap<>()); set(bean, patternParts.subList(0, patternParts.size() - 1), new HashMap<>());
@ -132,7 +146,6 @@ public class BeanPath implements Serializable{
BeanUtil.setFieldValue(subBean, patternParts.get(patternParts.size() - 1), value); BeanUtil.setFieldValue(subBean, patternParts.get(patternParts.size() - 1), value);
} }
// ------------------------------------------------------------------------------------------------------------------------------------- Private method start
/** /**
* 获取Bean中对应表达式的值 * 获取Bean中对应表达式的值
* *
@ -141,7 +154,7 @@ public class BeanPath implements Serializable{
* @param ignoreLast 是否忽略最后一个值忽略最后一个值则用于set否则用于read * @param ignoreLast 是否忽略最后一个值忽略最后一个值则用于set否则用于read
* @return 如果对应值不存在则返回null * @return 如果对应值不存在则返回null
*/ */
private Object get(List<String> patternParts, Object bean, boolean ignoreLast) { private Object get(final List<String> patternParts, final Object bean, final boolean ignoreLast) {
int length = patternParts.size(); int length = patternParts.size();
if (ignoreLast) { if (ignoreLast) {
length--; length--;
@ -166,7 +179,7 @@ public class BeanPath implements Serializable{
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Object getFieldValue(Object bean, String expression) { private static Object getFieldValue(final Object bean, final String expression) {
if (StrUtil.isBlank(expression)) { if (StrUtil.isBlank(expression)) {
return null; return null;
} }
@ -174,8 +187,8 @@ public class BeanPath implements Serializable{
if (StrUtil.contains(expression, ':')) { if (StrUtil.contains(expression, ':')) {
// [start:end:step] 模式 // [start:end:step] 模式
final List<String> parts = StrUtil.splitTrim(expression, ':'); final List<String> parts = StrUtil.splitTrim(expression, ':');
int start = Integer.parseInt(parts.get(0)); final int start = Integer.parseInt(parts.get(0));
int end = Integer.parseInt(parts.get(1)); final int end = Integer.parseInt(parts.get(1));
int step = 1; int step = 1;
if (3 == parts.size()) { if (3 == parts.size()) {
step = Integer.parseInt(parts.get(2)); step = Integer.parseInt(parts.get(2));
@ -218,13 +231,14 @@ public class BeanPath implements Serializable{
* *
* @param expression 表达式 * @param expression 表达式
*/ */
private void init(String expression) { private void init(final String expression) {
List<String> localPatternParts = new ArrayList<>(); final List<String> localPatternParts = new ArrayList<>();
int length = expression.length(); final int length = expression.length();
final StrBuilder builder = StrUtil.strBuilder(); final StringBuilder builder = new StringBuilder();
char c; char c;
boolean isNumStart = false;// 下标标识符开始 boolean isNumStart = false;// 下标标识符开始
boolean isInWrap = false; //标识是否在引号内
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
c = expression.charAt(i); c = expression.charAt(i);
if (0 == i && '$' == c) { if (0 == i && '$' == c) {
@ -233,7 +247,13 @@ public class BeanPath implements Serializable{
continue; continue;
} }
if (ArrayUtil.contains(EXP_CHARS, c)) { if('\'' == c){
// 结束
isInWrap = (false == isInWrap);
continue;
}
if (false == isInWrap && ArrayUtil.contains(EXP_CHARS, c)) {
// 处理边界符号 // 处理边界符号
if (CharUtil.BRACKET_END == c) { if (CharUtil.BRACKET_END == c) {
// 中括号数字下标结束 // 中括号数字下标结束
@ -253,9 +273,9 @@ public class BeanPath implements Serializable{
// 每一个边界符之前的表达式是一个完整的KEY开始处理KEY // 每一个边界符之前的表达式是一个完整的KEY开始处理KEY
} }
if (builder.length() > 0) { if (builder.length() > 0) {
localPatternParts.add(unWrapIfPossible(builder)); localPatternParts.add(builder.toString());
} }
builder.reset(); builder.setLength(0);
} else { } else {
// 非边界符号追加字符 // 非边界符号追加字符
builder.append(c); builder.append(c);
@ -267,25 +287,12 @@ public class BeanPath implements Serializable{
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, length - 1)); throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, length - 1));
} else { } else {
if (builder.length() > 0) { if (builder.length() > 0) {
localPatternParts.add(unWrapIfPossible(builder)); localPatternParts.add(builder.toString());
} }
} }
// 不可变List // 不可变List
this.patternParts = Collections.unmodifiableList(localPatternParts); this.patternParts = ListUtil.unmodifiable(localPatternParts);
} }
//endregion
/**
* 对于非表达式去除单引号
*
* @param expression 表达式
* @return 表达式
*/
private static String unWrapIfPossible(CharSequence expression) {
if (StrUtil.containsAny(expression, " = ", " > ", " < ", " like ", ",")) {
return expression.toString();
}
return StrUtil.unWrap(expression, '\'');
}
// ------------------------------------------------------------------------------------------------------------------------------------- Private method end
} }

View File

@ -28,7 +28,6 @@ import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.function.BiFunction; import java.util.function.BiFunction;
/** /**
@ -1433,7 +1432,7 @@ public class MapUtil {
*/ */
public static <K, V> Map.Entry<K, V> entry(K key, V value, boolean isImmutable) { public static <K, V> Map.Entry<K, V> entry(K key, V value, boolean isImmutable) {
return isImmutable ? return isImmutable ?
new AbstractMap.SimpleEntry<>(key, value) : new AbstractMap.SimpleImmutableEntry<>(key, value) :
new AbstractMap.SimpleImmutableEntry<>(key, value); new AbstractMap.SimpleEntry<>(key, value);
} }
} }