This commit is contained in:
Looly 2022-03-25 00:53:51 +08:00
parent e5bc9d5484
commit e76d2e13cb
5 changed files with 55 additions and 31 deletions

View File

@ -3,10 +3,8 @@ package cn.hutool.core.lang.func;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.text.CharPool;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
@ -57,18 +55,6 @@ public class LambdaUtil {
return resolve(func).getImplMethodName();
}
/**
* 获取lambda实现类
*
* @param func lambda
* @param <P> 类型
* @return lambda实现类
*/
public static <P> Class<P> getInstantiatedClass(Func1<P, ?> func) {
String instantiatedMethodType = resolve(func).getInstantiatedMethodType();
return ClassUtil.loadClass(StrUtil.replace(StrUtil.sub(instantiatedMethodType, 2, StrUtil.indexOf(instantiatedMethodType, ';')), StrPool.SLASH, StrPool.DOT));
}
/**
* 获取lambda表达式函数方法名称
*
@ -82,16 +68,44 @@ public class LambdaUtil {
}
/**
* 获取lambda实现类
* 通过对象的方法或类的静态方法引用获取lambda实现类两种情况匹配到此方法
* <ul>
* <li>对象方法引用myTeacher::getAge</li>
* <li>类静态方法引用MyTeacher::takeAge</li>
* </ul>
* 如想获取调用的方法引用所在类可以
* <pre>
* // 返回MyTeacher.class
* LambdaUtil.getImplClass(myTeacher::getAge);
* </pre>
*
* @param func lambda
* @param <R> 类型
* @return lambda实现类
* @since 5.8.0
*/
public static <R> Class<R> getImplClass(Func0<?> func) {
return ClassUtil.loadClass(resolve(func).getImplClass().replace(CharPool.SLASH, CharPool.DOT));
}
/**
* 通过类的方法引用获取lambda实现类<br>
* 类方法引用相当于获取的方法引用是MyTeacher.getAge(this)
* 如想获取调用的方法引用所在类可以
* <pre>
* // 返回MyTeacher.class
* LambdaUtil.getImplClass(MyTeacher::getAge);
* </pre>
*
* @param func lambda
* @param <T> 类型
* @return lambda实现类
* @since 5.8.0
*/
public static <T> Class<T> getImplClass(Func1<T, ?> func) {
return ClassUtil.loadClass(resolve(func).getImplClass().replace(CharPool.SLASH, CharPool.DOT));
}
/**
* 获取lambda表达式Getter或Setter函数方法对应的字段名称规则如下
* <ul>

View File

@ -550,7 +550,7 @@ public class MapUtil {
* @since 5.0.4
*/
public static String sortJoin(Map<?, ?> params, String separator, String keyValueSeparator, boolean isIgnoreNull,
String... otherParams) {
String... otherParams) {
return join(sort(params), separator, keyValueSeparator, isIgnoreNull, otherParams);
}
@ -672,7 +672,7 @@ public class MapUtil {
/**
* 变更<br>
* 通过biFunction自定义一个规则此规则将原Map中的元素转换成新的元素生成新的Map返回<br>
* 变更过程通过传入的 {@link BiFunction} 实现来返回一个值可以为不同类型的 {@link Map}
*
* @param map 原有的map
@ -680,9 +680,10 @@ public class MapUtil {
* @param <K> {@code key}的类型
* @param <V> {@code value}的类型
* @param <R> 新的修改后的{@code value}的类型
* @return 值可以为不同类型的 {@link Map}
* @return 值可以为不同类型的 {@link Map
* @since 5.8.0
*/
public static <K, V, R> Map<K, R> change(Map<K, V> map, BiFunction<K, V, R> biFunction) {
public static <K, V, R> Map<K, R> map(Map<K, V> map, BiFunction<K, V, R> biFunction) {
if (null == map || null == biFunction) {
return MapUtil.newHashMap();
}

View File

@ -221,7 +221,7 @@ public class EnumUtil {
* @return 对应枚举 获取不到时为 {@code null}
*/
public static <E extends Enum<E>, C> E getBy(Func1<E, C> condition, C value) {
return Arrays.stream(LambdaUtil.getInstantiatedClass(condition).getEnumConstants()).filter(e -> condition.callWithRuntimeException(e).equals(value)).findAny().orElse(null);
return Arrays.stream(LambdaUtil.getImplClass(condition).getEnumConstants()).filter(e -> condition.callWithRuntimeException(e).equals(value)).findAny().orElse(null);
}
/**
@ -236,7 +236,7 @@ public class EnumUtil {
* @return 对应枚举中另一字段值 获取不到时为 {@code null}
*/
public static <E extends Enum<E>, F, C> F getFieldBy(Function<E, F> field, Func1<E, C> condition, C value) {
return Arrays.stream(LambdaUtil.getInstantiatedClass(condition).getEnumConstants()).filter(e -> condition.callWithRuntimeException(e).equals(value)).findAny().map(field).orElse(null);
return Arrays.stream(LambdaUtil.getImplClass(condition).getEnumConstants()).filter(e -> condition.callWithRuntimeException(e).equals(value)).findAny().map(field).orElse(null);
}
/**

View File

@ -1,10 +1,9 @@
package cn.hutool.core.lang.func;
import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
import lombok.Data;
public class LambdaUtilTest {
@Test
@ -21,19 +20,29 @@ public class LambdaUtilTest {
@Test
public void getImplClassTest() {
// 一般用于封装工具类时减少参数使用
Class<MyTeacher> aClass = LambdaUtil.getInstantiatedClass(MyTeacher::getAge);
// 类方法引用相当于获取的方法引用是MyTeacher.getAge(this)
// 因此此处会匹配到Func1其参数就是this
Class<MyTeacher> aClass = LambdaUtil.getImplClass(MyTeacher::getAge);
Assert.assertEquals(MyTeacher.class, aClass);
// 一般用于封装工具类时减少参数使用
MyTeacher myTeacher = new MyTeacher();
Class<MyTeacher> bClass = LambdaUtil.getImplClass(myTeacher::getAge);
Assert.assertEquals(MyTeacher.class, bClass);
// 对象方法引用因为已经有了对象因此此处引用相当于获取myTeacher.getAge()
aClass = LambdaUtil.getImplClass(myTeacher::getAge);
Assert.assertEquals(MyTeacher.class, aClass);
// 静态方法引用相当于获取MyTeader.takeAge
aClass = LambdaUtil.getImplClass(MyTeacher::takeAge);
Assert.assertEquals(MyTeacher.class, aClass);
}
@Data
static class MyTeacher {
public static String takeAge(){
return new MyTeacher().getAge();
}
public String age;
}
}

View File

@ -56,7 +56,7 @@ public class MapUtilTest {
}
@Test
public void changeTest() {
public void mapTest() {
// Add test like a foreigner
Map<Integer, String> adjectivesMap = MapUtil.<Integer, String>builder()
.put(0, "lovely")
@ -64,7 +64,7 @@ public class MapUtilTest {
.put(2, "happily")
.build();
Map<Integer, String> resultMap = MapUtil.change(adjectivesMap, (k, v) -> v + " " + PeopleEnum.values()[k].name().toLowerCase());
Map<Integer, String> resultMap = MapUtil.map(adjectivesMap, (k, v) -> v + " " + PeopleEnum.values()[k].name().toLowerCase());
Assert.assertEquals("lovely girl", resultMap.get(0));
Assert.assertEquals("friendly boy", resultMap.get(1));
@ -80,7 +80,7 @@ public class MapUtilTest {
Map<Long, List<Long>> groupIdUserIdsMap = groups.stream().flatMap(group -> idUserMap.keySet().stream().map(userId -> UserGroup.builder().groupId(group.getId()).userId(userId).build())).collect(Collectors.groupingBy(UserGroup::getUserId, Collectors.mapping(UserGroup::getGroupId, Collectors.toList())));
// 神奇的魔法发生了 分组id和用户ids组成的map竟然变成了订单编号和用户实体集合组成的map
Map<Long, List<User>> groupIdUserMap = MapUtil.change(groupIdUserIdsMap, (groupId, userIds) -> userIds.stream().map(idUserMap::get).collect(Collectors.toList()));
Map<Long, List<User>> groupIdUserMap = MapUtil.map(groupIdUserIdsMap, (groupId, userIds) -> userIds.stream().map(idUserMap::get).collect(Collectors.toList()));
// 然后你就可以拿着这个map去封装groups使其能够在订单数据带出客户信息啦
groups.forEach(group -> Opt.ofNullable(group.getId()).map(groupIdUserMap::get).ifPresent(group::setUsers));