java实现的类似于sql join操作的工具类,通用递归,最低需要java8
阅读原文时间:2023年08月29日阅读:2

直接上代码,缺包的自行替换为自己项目中存在的

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);  
        }  
    }  
}  

}