java实现的类似于sql join操作的工具类(java集合的一对多,一对一关联操作),通用递归,最低需要java8
直接上代码,缺包的自行替换为自己项目中存在的
import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import cn.hutool.core.util.ObjectUtil; /** * @description:数据列表关联,类似于sql中的join * @author: Binz * @time:2019-09-29 09:40 */ public class Java8Util { private static final Logger logger = LoggerFactory.getLogger(Java8Util.class); /** * @description:关联到主表的基本类型属性去 一对多 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: toT1ListProperty 需要赋值到t1的List属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如:Java8Util.joinToList(users, roles, User::getId, Role::getUserId, User::setRoles); * </pre> */ public static <P,C,JR> void joinToList(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,BiConsumer<P,List<C>> toT1ListProperty) { try { Map<Object,List<C>> valueMap = new HashMap<>(); JR t2JoinValue; for (C c : t2) { t2JoinValue = t2JoinKey.apply(c); valueMap.putIfAbsent(t2JoinValue, new ArrayList<>()); valueMap.get(t2JoinValue).add(c); } JR t1JoinValue; List<C> list; for (P p : t1) { t1JoinValue = t1JoinKey.apply(p); list = valueMap.get(t1JoinValue); toT1ListProperty.accept(p, list); } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对多 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: getT2PropertyKey 获取t2指定属性 * @param: toT1ListProperty 需要赋值到t1的List属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如:Java8Util.joinToListProperty(users, roles, User::getId, Role::getUserId, Role::Id ,Role::getName , User::setRoleNames); * </pre> */ public static <P,C,JR,SR> void joinToListProperty(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,Function<C, SR> getT2PropertyKey ,BiConsumer<P,List<SR>> toT1PropertyKey) { try { Map<Object,List<SR>> valueMap = new HashMap<>(); JR t2JoinValue; for (C c : t2) { t2JoinValue = t2JoinKey.apply(c); valueMap.putIfAbsent(t2JoinValue, new ArrayList<>()); valueMap.get(t2JoinValue).add(getT2PropertyKey.apply(c)); } JR t1JoinValue; List<SR> list; for (P p : t1) { t1JoinValue = t1JoinKey.apply(p); list = valueMap.get(t1JoinValue); toT1PropertyKey.accept(p,list); } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } public static <P,C,JR,SR> void joinToSetProperty(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,Function<C, SR> getT2PropertyKey ,BiConsumer<P,Set<SR>> toT1PropertyKey) { try { Map<Object,Set<SR>> valueMap = new HashMap<>(); JR t2JoinValue; for (C c : t2) { t2JoinValue = t2JoinKey.apply(c); valueMap.putIfAbsent(t2JoinValue, new HashSet<>()); valueMap.get(t2JoinValue).add(getT2PropertyKey.apply(c)); } JR t1JoinValue; Set<SR> list; for (P p : t1) { t1JoinValue = t1JoinKey.apply(p); list = valueMap.get(t1JoinValue); toT1PropertyKey.accept(p,list); } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对一 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: toT1PropertyKey 把t2 设置到 t1指定的属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如:joinToEntity(users, accountss, User::getId, Account::getUserId, User::setAccount); * </pre> */ public static <P,C,JR> void joinToEntity(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,BiConsumer<P,C> toT1EntityProperty) { try { Map<Object,List<P>> m1 = new HashMap<>(t1.size()); Object t1KeyValue; for (P p : t1) { t1KeyValue = t1JoinKey.apply(p); m1.putIfAbsent(t1KeyValue, new ArrayList<>()); m1.get(t1KeyValue).add(p); } Object t2JoinKeyValue; List<P> ps; for (C c : t2) { t2JoinKeyValue = t2JoinKey.apply(c); ps = m1.get(t2JoinKeyValue); if(ps != null) { for (P p : ps) { toT1EntityProperty.accept(p, c); } } } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对一 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: getT2PropertyKey 从t2获取某一个值 * @param: toT1PropertyKey 把t2获取到的值设置到 t1指定的属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如:joinToEntity(users, accountss, User::getId, Account::getUserId, User::setAccount); * </pre> */ public static <P,C,JR> void joinToEntityByFilter(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,Predicate<P> t1Filter,Predicate<C> t2Filter,BiConsumer<P,C> toT1EntityProperty) { try { Map<Object,List<P>> m1 = new HashMap<>(t1.size()); Object t1KeyValue; for (P p : t1) { if(t1Filter == null || t1Filter.test(p)) { t1KeyValue = t1JoinKey.apply(p); m1.putIfAbsent(t1KeyValue, new ArrayList<>()); m1.get(t1KeyValue).add(p); } } Object t2JoinKeyValue; List<P> ps; for (C c : t2) { if(t2Filter == null || t2Filter.test(c)) { t2JoinKeyValue = t2JoinKey.apply(c); ps = m1.get(t2JoinKeyValue); if(ps != null) { for (P p : ps) { toT1EntityProperty.accept(p, c); } } } } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对一 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: getT2PropertyKey 从t2获取某一个值 * @param: toT1PropertyKey 把t2获取到的值设置到 t1指定的属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如:joinToProperty(users, persons, User::getId, Person::getUserId, Person::getRealName User::setRealName); * </pre> */ public static <P,C,JR,SR> void joinToProperty(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,Function<C, SR> getT2PropertyKey ,BiConsumer<P,SR> toT1PropertyKey) { try { Map<Object,List<P>> m1 = new HashMap<>(t1.size()); Object t1KeyValue; for (P p : t1) { t1KeyValue = t1JoinKey.apply(p); m1.putIfAbsent(t1KeyValue, new ArrayList<>()); m1.get(t1KeyValue).add(p); } Object t2JoinKeyValue; List<P> ps; for (C c : t2) { t2JoinKeyValue = t2JoinKey.apply(c); ps = m1.get(t2JoinKeyValue); if(ps != null) { for (P p : ps) { toT1PropertyKey.accept(p, getT2PropertyKey.apply(c)); } } } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对一 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: t1Filter 表一过滤 可为空 * @param: t2Filter 表二过滤 可为空 * @param: getT2PropertyKey 从t2获取某一个值 * @param: toT1PropertyKey 把t2获取到的值设置到 t1指定的属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如: * joinToPropertyByFilter(users, persons, User::getPersonId, Person::getId, e -> { return e.getId() != null && e.getId() > 3; },null, Person::getRealName, User::setRealName); * </pre> */ public static <P,C,JR,SR> void joinToPropertyByFilter(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,Predicate<P> t1Filter,Predicate<C> t2Filter,Function<C, SR> getT2PropertyKey ,BiConsumer<P,SR> toT1PropertyKey) { try { Map<Object,List<P>> m1 = new HashMap<>(t1.size()); Object t1KeyValue; for (P p : t1) { if(t1Filter == null || t1Filter.test(p)) { t1KeyValue = t1JoinKey.apply(p); m1.putIfAbsent(t1KeyValue, new ArrayList<>()); m1.get(t1KeyValue).add(p); } } Object t2JoinKeyValue; List<P> ps; for (C c : t2) { if(t2Filter == null || t2Filter.test(c)) { t2JoinKeyValue = t2JoinKey.apply(c); ps = m1.get(t2JoinKeyValue); if(ps != null) { for (P p : ps) { toT1PropertyKey.accept(p, getT2PropertyKey.apply(c)); } } } } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对一 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: getT2PropertyKey 从t2获取某一个值 * @param: toT1PropertyKey 把t2获取到的值设置到 t1指定的属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如: * joinToPropertys(users, persons, User::getPersonId, Person::getId, (user,person)->{ * user.setRealName("乱设置的"+person.getId()); * user.setAge(person.getAge()); * }); * </pre> */ public static <P,C,JR,SR> void joinToPropertys(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey,BiConsumer<P,C> toT1Propertys) { try { Map<Object,List<P>> m1 = new HashMap<>(t1.size()); Object t1KeyValue; for (P p : t1) { t1KeyValue = t1JoinKey.apply(p); m1.putIfAbsent(t1KeyValue, new ArrayList<>()); m1.get(t1KeyValue).add(p); } Object t2JoinKeyValue; List<P> ps; for (C c : t2) { t2JoinKeyValue = t2JoinKey.apply(c); ps = m1.get(t2JoinKeyValue); if(ps != null) { for (P p : ps) { toT1Propertys.accept(p, c); } } } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * @description:关联到主表的基本类型属性去 一对一 * @param: t1 主表 * @param: t2 关联表 * @param: t1JoinKey 主表的关联key * @param: t2JoinKey 关联表的关联key * @param: getT2PropertyKey 从t2获取某一个值 * @param: toT1PropertyKey 把t2获取到的值设置到 t1指定的属性 * @return * @author: Binz * @time:2019-09-29 09:44 * <pre> * 例如: * joinToPropertysByFilter(users, persons, User::getPersonId, Person::getId , e -> { return e.getId() != null && e.getId() > 3; }, (t1,t2)->{ t1.setRealName("有过滤的乱设置的"+t2.getId()); t2.setAge(1); }); * </pre> */ public static <P,C,JR,SR> void joinToPropertysByFilter(Collection<P> t1, Collection<C> t2,Function<P, JR> t1JoinKey ,Function<C,JR> t2JoinKey , Predicate<P> t1Filter,BiConsumer<P,C> toT1Propertys) { try { Map<Object,List<P>> m1 = new HashMap<>(t1.size()); Object t1KeyValue; for (P p : t1) { if(t1Filter.test(p)) { t1KeyValue = t1JoinKey.apply(p); m1.putIfAbsent(t1KeyValue, new ArrayList<>()); m1.get(t1KeyValue).add(p); } } Object t2JoinKeyValue; List<P> ps; for (C c : t2) { t2JoinKeyValue = t2JoinKey.apply(c); ps = m1.get(t2JoinKeyValue); if(ps != null) { for (P p : ps) { toT1Propertys.accept(p, c); } } } } catch (Exception e) { logger.error( ExceptionUtils.getStackTrace(e)); } } /** * 通用递归,使用示例 * <br/>List<DepartmentTreeVo> list = new ArrayList<>(); * <br/>Java8Util.recursion(departmentTree, DepartmentTreeVo::getChildren, t -> { * <br/> list.add(t); * <br/>}); * @param ts * @param childsFn * @param then */ public static <T> void recursion(List<T> ts, Function<T, List<T>> childsFn , Consumer<T> then) { for(T t : ts) { then.accept(t); } for(T t : ts) { List<T> childs = childsFn.apply(t); if(ObjectUtil.isNotEmpty(childs)) { recursion(childs, childsFn, then); } } } }
分类:
java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix