好用的工具类(长期更新)

zionchen / 2024-02-23 / 原文

1、笛卡尔积工具
记不得参考谁的了,原文不贴了
入参结构List<List>

实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author zionchen
 * @date 2023/9/25 11:39
 */
public class DescartesUtil {

    /**
     * n个list 元素笛卡尔积
     * @param list
     * @return
     * @param <T>
     */
    public static <T> List<List<T>> getDescartes(List<List<T>> list) {
        List<List<T>> returnList = new ArrayList<>();
        descartesRecursive(list, 0, returnList, new ArrayList<T>());
        return returnList;
    }

    /**
     * 递归实现
     * 原理:从原始list的0开始依次遍历到最后
     *
     * @param originalList 原始list
     * @param position     当前递归在原始list的position
     * @param returnList   返回结果
     * @param cacheList    临时保存的list
     */
    private static <T> void descartesRecursive(List<List<T>> originalList, int position, List<List<T>> returnList, List<T> cacheList) {
        List<T> originalItemList = originalList.get(position);
        for (int i = 0; i < originalItemList.size(); i++) {
            //最后一个复用cacheList
            List<T> childCacheList = (i == originalItemList.size() - 1) ? cacheList : new ArrayList<>(cacheList);
            childCacheList.add(originalItemList.get(i));
            if (position == originalList.size() - 1) {
                //遍历到最后退出递归
                returnList.add(childCacheList);
                continue;
            }
            descartesRecursive(originalList, position + 1, returnList, childCacheList);
        }
    }

    public static void main(String[] args) {
        List<List<String>> listData = new ArrayList<>();
        listData.add(Arrays.asList("A1", "B1"));
        listData.add(Arrays.asList("A2", "B2"));
        listData.add(Arrays.asList("A3", "B3"));
//        listData.add(Arrays.asList("A4", "B4"));
        List<List<String>> lisReturn = getDescartes(listData);
        System.out.println(lisReturn);
        System.out.println(lisReturn.size());
    }

}

2、mybatis批量插入

基础类
public interface StatusEnum {
    String getCode();
    String getDesc();
}


public enum ErrorCodeEnum implements StatusEnum {
  BASH_INSERT_ERROR("10004","mybatis批量入库出错");
  private String code;

  private String desc;

  ErrorCodeEnum(String code,String desc){
      this.code = code;
      this.desc = desc;
  }

  @Override
  public String getCode() {
      return code;
  }

  @Override
  public String getDesc() {
      return desc;
  }
}

实现
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.Resource;
import java.util.List;
import java.util.function.BiFunction;

/**
 * @author zionchen
 * @date 2023/8/25 16:08
 */
@Component
public class MybatisBatchUtils {

    /**
     * 每次处理1000条
     */
    private static final int BATCH_SIZE = 1000;

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 批量处理修改或者插入
     * 使用方式   batchUtils.batchUpdateOrInsert(数据集合, item -> mapper实例对象.insert方法(item));
     *
     * @param data        需要被处理的数据
     * @param mapperClass Mybatis的Mapper类
     * @param function    自定义处理逻辑
     * @return int 影响的总行数
     */
    public <T, U, R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T, U, R> function) {
        int i = 1;
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            // 开启事务
            batchSqlSession.getConnection().setAutoCommit(false);
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                function.apply(element, mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    batchSqlSession.flushStatements();
                }
                i++;
            }
            // 非事务环境下强制commit,事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new AppException(ErrorCodeEnum.BASH_INSERT_ERROR);
        } finally {
            batchSqlSession.close();
        }
        return i - 1;
    }
}

应用
    @Resource
    private MybatisBatchUtils mybatisBatchUtils;

    mybatisBatchUtils.batchUpdateOrInsert(testEntity, TestMapper.class, (e, testTempMapper) -> testMapper.insert(e));

3、map合并
将2个map合并,重复的key使用map1的

点击查看代码
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * map合并工具
 *
 * @author zionchen
 * @date 2023/11/2 16:20
 */
public class MergeMapUtil {

    /**
     * 合并 两个map  有重复key时应用 map1的值
     * @param map1
     * @param map2
     * @return
     * @param <K>
     * @param <V>
     */
    public static <K, V> Map<K, V> mergeMaps(Map<K, V> map1, Map<K, V> map2) {
        BinaryOperator<V> mergeFunction = (v1, v2) -> v1;
        return Stream.of(map1, map2)
                .flatMap(map -> map.entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, mergeFunction));
    }
}