主副表之间相互对应的工具类

背景

​ 在工作的过程中经常遇到一种场景:某个查询要求效率比较高,而且需要的数据分布在不同的表之中,往往我们需要查询一个主表拿到数据之后,再拿主表的id或者其它识别符号去查询从表的数据。

​ 为了查询效率比较高,那么我们查从表的时候如果使用for循环去查找效率会比较慢,这个可以验证。这个时候推荐使用in语句查询一次性把所有的结果找出来再在内存中做匹配。

​ 这里我需要做一个主副表的匹配,把副表的值映射到主表之中。

模拟主副表

主表Parent

import java.util.List;

public class Parent {

    private Long id;
    private String code;
    private String name;

    List<Child> children;

    Child oneChild;

    public Parent(Long id, String code, String name) {
        this.id = id;
        this.code = code;
        this.name = name;
    }

    public Child getOneChild() {
        return oneChild;
    }

    public void setOneChild(Child oneChild) {
        this.oneChild = oneChild;
    }

    public List<Child> getChildren() {
        return children;
    }

    public void setChildren(List<Child> children) {
        this.children = children;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

副表Child


public class Child {

    public Child(Long id, Long parentId, String name, String code) {
        this.id = id;
        this.parentId = parentId;
        this.name = name;
        this.code = code;
    }

    private Long id;
    private Long parentId;
    private String name;
    private String code;

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

对应的映射代码


public final class ListBeanMap {

    /**
     * 一对多映射
     * @param parents  父节点
     * @param children 子节点
     * @param parentId 父节点对应子节点的字段
     * @param childId  子节点对应父节点的字段
     * @param action   父节点的set方法,将子节点对应的数据set到父节点
     * @param <T>      父节点的类型
     * @param <K>      子节点的类型
     * @param <U>      父子节点使用何种类型来做对应
     * @return         返回值只是为了在return的时候比较方便,其实在做映射的时候,对应的值已经set到父节点之中。
     */
    public static <T,K,U> List<T> one2Many(List<T> parents, List<K> children,
                                           Function<? super T, ? extends U> parentId,
                                           Function<? super K, ? extends U> childId,
                                           BiConsumer<? super T,? super List<K>> action) {
        if (CollectionUtils.isEmpty(parents) || CollectionUtils.isEmpty(children)) {
            return new ArrayList<>();
        }
        Map<U, T> pMap = parents.stream().collect(Collectors.toMap(parentId, p -> p));
        Map<U, List<K>> cMap = children.stream().collect(Collectors.toMap(childId,
                Lists::newArrayList,
                (List<K> oldList, List<K> newList) -> {
            oldList.addAll(newList);
            return oldList;
        }));
        pMap.forEach((k,v) -> action.accept(v, cMap.get(k)));
        return parents;
    }

        /**
     * 一对一映射
     * @param parents  父节点
     * @param children 子节点
     * @param parentId 父节点对应子节点的字段
     * @param childId  子节点对应父节点的字段
     * @param action   父节点的set方法,将子节点对应的数据set到父节点
     * @param <T>      父节点的类型
     * @param <K>      子节点的类型
     * @param <U>      父子节点使用何种类型来做对应
     * @return         返回值只是为了在return的时候比较方便,其实在做映射的时候,对应的值已经set到父节点之中。
     */
    public static <T,K,U> List<T> one2One(List<T> parents, List<K> children,
                                           Function<? super T, ? extends U> parentId,
                                           Function<? super K, ? extends U> childId,
                                           BiConsumer<? super T,? super K> action) {
        if (CollectionUtils.isEmpty(parents) || CollectionUtils.isEmpty(children)) {
            return new ArrayList<>();
        }
        Map<U, T> pMap = parents.stream().collect(Collectors.toMap(parentId, p -> p));
        Map<U, K> cMap = children.stream().collect(Collectors.toMap(childId, c -> c));
        pMap.forEach((k,v) -> action.accept(v, cMap.get(k)));
        return parents;
    }

}

测试类

    public static void main(String[] args) {
        List<Parent> parents = new ArrayList<>(1000);
        List<Child> children = new ArrayList<>(1000);
        for (long i = 0; i < 1000; i++) {
            parents.add(new Parent(i,String.format("%010d", (long)(100000000 * Math.random())), "test"+i));
            children.add(new Child(1000-i, i,"test"+(1000-i), String.format("%010d", (long)(100000000 * Math.random()))));
        }

        ListBeanMap.one2Many(parents, children, Parent::getId, Child::getParentId, Parent::setChildren);
        ListBeanMap.one2One(parents, children, Parent::getId, Child::getParentId, Parent::setOneChild);

        System.out.println(JSON.toJSONString(parents));

    }

测试结果(另外几种测试场景因为时间关系就不做了,如果发现问题,欢迎留言):

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值