前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、Java 分段

@Slf4j
public class BigDataSubUtils {

    // /**
    //  * 1、获取分段结果
    //  */
    // public static void main(String[] args) {
    //     int totalCount = 0;
    //     int intervalLength = 5;
    //     List<ImmutablePair<Integer, Integer>> result = intervalPairOfTotalCount(totalCount, intervalLength);
    //     // result.forEach(item -> System.out.println(item.getLeft() + "-" + item.getRight()));
    //
    //     List<String> list = Lists.newArrayList("1","2","3","4","5");
    //     List<List<String>> lists = intervalPairOfTotalCount(list, 6);
    //     lists.forEach(item -> {
    //         item.forEach(item2->{
    //             System.out.printf(item2);
    //         });
    //         System.out.println();
    //     });
    // }


    /**
     * 获取分段区间,索引从0开始,注意下游
     *
     * @param totalCount 总数量
     * @param pageSize   区间长度
     */
    public static List<ImmutablePair<Integer, Integer>> sizeSub(Integer totalCount, Integer pageSize) {
        List<ImmutablePair<Integer, Integer>> result = new ArrayList<>();

        Integer pageCount;
        if (totalCount % pageSize == 0) {
            pageCount = totalCount / pageSize;
        } else {
            pageCount = totalCount / pageSize + 1;
        }

        Integer pageNow = 1;
        while (pageNow <= pageCount) {
            int startIndex = (pageNow - 1) * pageSize;
            int endIndex = pageNow.compareTo(pageCount) != 0 ? startIndex + pageSize : totalCount;
            ImmutablePair<Integer, Integer> pair = ImmutablePair.of(startIndex, endIndex);
            pageNow++;
            result.add(pair);
        }
        return result;
    }


    /**
     * 获取分段区间
     *
     * @param list     数据
     * @param pageSize 区间长度
     */
    public static <T> List<List<T>> listSub(List<T> list, Integer pageSize) {
        Integer totalCount = list.size();
        List<List<T>> result = new ArrayList<>();

        Integer pageCount;
        if (totalCount % pageSize == 0) {
            pageCount = totalCount / pageSize;
        } else {
            pageCount = totalCount / pageSize + 1;
        }

        Integer pageNow = 1;
        while (pageNow <= pageCount) {
            int startIndex = (pageNow - 1) * pageSize;
            int endIndex = pageNow.compareTo(pageCount) != 0 ? startIndex + pageSize : totalCount;
            List<T> sonList = list.subList(startIndex, endIndex);
            pageNow++;
            result.add(sonList);
        }
        return result;
    }

}

2、RPC 多次查(分页)

注意下游bug导致无线死循环,防止方法,设置方法请求次数或者设置超时时间

2.1、普通调用

public Set<String> queryAllSigningVendorIds(SignUpStatusQueryReq signUpStatusQueryReq) {
  Set<String> result = new HashSet<>();
  PageQueryRequest<SignUpStatusQueryReq> pageQueryRequest = new PageQueryRequest<>();
  pageQueryRequest.setQuery(signUpStatusQueryReq);
  pageQueryRequest.setPageIndex(NumberConstant.ONE);
  pageQueryRequest.setPageSize(NumberConstant.TEN_THOUSAND);
  try {
    while (true) {
      PageQueryResponse<String> response = signResource.querySigningVendorIdsPage(pageQueryRequest);
      if (response != null && Boolean.TRUE.equals(response.getSuccess())) {
        if (CollectionUtils.isEmpty(response.getValues())) {
          return result;
        }
        result.addAll(response.getValues());
        if (response.getValues().size() < pageQueryRequest.getPageSize()){
          return result;
        }
        pageQueryRequest.setPageIndex(pageQueryRequest.getPageIndex() + NumberConstant.ONE);
        continue;
      }
      log.error("SignResourceRpc#queryAllSigningVendorIds] FAIL, request:{}, response:{}", 
                JSON.toJSONString(signUpStatusQueryReq), JSON.toJSONString(response));
      throw new RuntimeException("查询所有在约的商家Id集合--接口数据异常");
    }
  } catch (Exception e) {
    log.error("SignResourceRpc#queryAllSigningVendorIds] ERROR, request:{}, e:{}", 
              JSON.toJSONString(signUpStatusQueryReq), ExceptionUtils.getStackTrace(e));
    throw new RuntimeException("查询在约的商家Id集合-接口调用异常");
  }
}

3、数据库多次查询(分页)

3.1、偏移量查询

public List<Route> selectByExample(RouteQuery query) {
  List<Route> result = new ArrayList<>();
  int pageNo = NumberConstant.ONE;
  int pageSize = NumberConstant.TEN_THOUSAND;
  while (true) {
    long start = System.currentTimeMillis();
    int offset = (pageNo - NumberConstant.ONE) * pageSize;
    query.setOffset(offset);
    query.setPageSize(pageSize);
    List<Route> list = routeMapper.selectByExample(query);
    if (CollectionUtils.isEmpty(list)) {
        return result;
    }
    pageNo = pageNo + 1;
    result.addAll(list);
    if (list.size() < pageSize){
      return result;
    }
  }
}

3.3、PageHelper


/**
 * queryAll
 *
 * @param function function
 * @param q        q
 * @param pageSize pageSize
 * @return {@link List<R>}
 */
public static <Q, R> List<R> queryAll(Function<Q, List<R>> function, Q q, int pageSize) {
    List<R> dbList = Lists.newArrayList();
    PageInfo<R> pageInfo;
    int pageNow = 1;
    while (true) {
        PageHelper.startPage(pageNow, pageSize);
        pageInfo = new PageInfo<>(function.apply(q));
        if (CollectionUtils.isEmpty(pageInfo.getList())) {
            break;
        }
        dbList.addAll(pageInfo.getList());
        pageNow = pageNow + 1;
    }
    return dbList;
}

4、Java 分页

4.1、简单分页

package com.hlj.util.z035_分页;

import com.google.common.collect.Lists;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.stream.Collectors;

/**
* java分页工具
* @author zhangyujin
* @date 2021/11/5  9:10 上午.
*/
@Slf4j
public class JavaPageUtils {


  public static void main(String[] args) {
      int pageNow = 3;
      int pageSize = 2;
      PageDto<String> page = toPageDto(Lists.newArrayList("1", "2", "3", "4", "5"), pageNow, pageSize);
      log.info("toPageDto:{}", page);
  }

  public static <T>  PageDto<T> toPageDto(List<T> list, Integer pageNow, Integer pageSize) {
      if  (list == null || list.isEmpty()){
          return new PageDto<>(null, pageNow, pageSize, 0, 0);
      }

      Integer totalCount = list.size();
      Integer pageCount;
      if (totalCount % pageSize == 0) {
          pageCount = totalCount / pageSize;
      } else {
          pageCount = totalCount / pageSize + 1;
      }

    
      List<T> pageList = list.stream().skip((long) (pageNow - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
      return new PageDto<>(pageList, pageNow, pageSize, totalCount, pageCount);
  }
  
  @Data
  @Accessors(chain = true)
  public static class PageDto<T> {
      private List<T> datas;
      /**
       * 当前页码数
       */
      private Integer pageNow;
      /**
       * 每页显示的记录数
       */
      private Integer pageSize;
      /**
       * 总记录数
       */
      private Integer totalCount;
      /**
       * 一共多少页
       */
      private Integer pageCount;

      public PageDto(List<T> datas, Integer pageNow, Integer pageSize, Integer totalCount, Integer pageCount) {
          this.datas = datas;
          this.pageNow = pageNow;
          this.pageSize = pageSize;
          this.totalCount = totalCount;
          this.pageCount = pageCount;
      }

      private PageDto(List<T> datas) {
          this.datas = datas;
      }

      private PageDto() {
      }
  }

}

4.1、匹配分页

package com.hlj.util.z035_分页;

import com.google.common.collect.Lists;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Stream 流分页
* @author zhangyujin
* @date 2023/5/30  11:51.
*/
@Slf4j
public class StreamPageUtils {

  public static void main(String[] args) {
      DemoDTO demo1 = new DemoDTO()
              .setPrice(new BigDecimal("1"))
              .setSkuName("大疆飞机V1")
              .setOrderId("111")
              .setCreateTime(LocalDateTime.now().minusDays(1));
      DemoDTO demo2 = new DemoDTO()
              .setPrice(new BigDecimal("1"))
              .setSkuName("大疆飞机V2")
              .setOrderId("222")
              .setCreateTime(LocalDateTime.now().minusDays(1));

      DemoDTO demo3 = new DemoDTO()
              .setPrice(new BigDecimal("1"))
              .setSkuName("大疆飞机V3")
              .setOrderId("333")
              .setCreateTime(LocalDateTime.now().minusDays(1));

      DemoDTO demo4 = new DemoDTO()
              .setPrice(new BigDecimal("1"))
              .setSkuName("大疆飞机V4")
              .setOrderId("444")
              .setCreateTime(LocalDateTime.now().minusDays(1));

      DemoDTO demo5 = new DemoDTO()
              .setPrice(new BigDecimal("1"))
              .setSkuName("大疆飞机V5")
              .setOrderId("555")
              .setCreateTime(LocalDateTime.now().minusDays(1));

      List<DemoDTO> list = Lists.newArrayList(demo1,demo2,demo3,demo4,demo5);
      DemoQuery query = new DemoQuery().setOrderId("111");
      PageDto<DemoDTO> page = toPageDto(query, list, 1, 1);
      log.info("page:{}", page);

      query = new DemoQuery().setSkuName("大疆飞机");
      page = toPageDto(query, list, 2, 3);
      log.info("page:{}", page);
  }

  public static  PageDto<DemoDTO> toPageDto(DemoQuery query, 
                                            List<DemoDTO> list, 
                                            Integer pageNow, 
                                            Integer pageSize) {
      if  (list == null || list.isEmpty()){
          return new PageDto<>(null, pageNow, pageSize, 0, 0);
      }

      Stream<DemoDTO> stream = list.stream();
      if (Objects.nonNull(query.getStartTime()) ) {
          stream = stream.filter(item->query.getStartTime().compareTo(item.getCreateTime()) <= 0);
      }
      if (Objects.nonNull(query.getEndTime()) ) {
          stream = stream.filter(item->query.getEndTime().compareTo(item.getCreateTime()) >= 0);
      }
      if (StringUtils.isNotBlank(query.getOrderId()) ) {
          stream = stream.filter(item->StringUtils.equals(query.getOrderId(), item.getOrderId()));
      }
      if (StringUtils.isNotBlank(query.getSkuName()) ) {
          stream = stream.filter(item-> item.getSkuName().contains(query.getSkuName()));
      }

      List<DemoDTO> matchList = stream
              .sorted(Comparator.comparing(DemoDTO::getCreateTime).reversed())
              .collect(Collectors.toList());

      Integer totalCount = matchList.size();
      Integer pageCount;
      if (totalCount % pageSize == 0) {
          pageCount = totalCount / pageSize;
      } else {
          pageCount = totalCount / pageSize + 1;
      }
      List<DemoDTO> pageList = matchList.stream()
              .skip((long) (pageNow - 1) * pageSize)
              .limit(pageSize)
              .collect(Collectors.toList());
      return new PageDto<>(pageList, pageNow, pageSize, totalCount, pageCount);
  }


  /**
   * @author zhangyujin
   * @date 2023/5/30  13:06.
   */
  @ToString
  @Accessors(chain = true)
  @Data
  public static class DemoDTO {

      private String orderId;

      private String skuName;

      private BigDecimal price;

      private LocalDateTime createTime;

  }


  /**
   * @author zhangyujin
   * @date 2023/5/30  13:06.
   */
  @ToString
  @Accessors(chain = true)
  @Data
  public static class DemoQuery {

      private String orderId;

      private String skuName;

      private BigDecimal price;

      private LocalDateTime startTime;

      private LocalDateTime endTime;

  }

  @ToString
  @Accessors(chain = true)
  public static class PageDto<T> {
      private List<T> datas;
      /**
       * 当前页码数
       */
      private Integer pageNow;
      /**
       * 每页显示的记录数
       */
      private Integer pageSize;
      /**
       * 总记录数
       */
      private Integer totalCount;
      /**
       * 一共多少页
       */
      private Integer pageCount;

      public PageDto(List<T> datas, Integer pageNow, Integer pageSize, Integer totalCount, Integer pageCount) {
          this.datas = datas;
          this.pageNow = pageNow;
          this.pageSize = pageSize;
          this.totalCount = totalCount;
          this.pageCount = pageCount;
      }

      private PageDto(List<T> datas) {
          this.datas = datas;
      }

      private PageDto() {
      }
  }

}


5、工具

/**
 * userDemoManager
 */
@Resource
private UserDemoManager userDemoManager;

/**
 * 大数据量-分页查询全部
 *
 * @param queryBo queryBo
 * @return List<UserDemoBO>
 */
@Override
public List<UserDemoBO> queryAllUserDemoByLimit(UserDemoQueryBO queryBo) {
    return BatchQueryUtils.queryAllByLimit(p -> userDemoManager.queryUserDemoPage(p), queryBo, 1000L);
}

/**
 * 大数据量-IdSize查询全部
 *
 * @param queryBo queryBo
 * @return List<UserDemoBO>
 */
@Override
public List<UserDemoBO> queryAllUserDemoByIdSize(UserDemoQueryBO queryBo) {
    IdQueryBO idQueryBO = new IdQueryBO(0L, 2L);
    List<UserDemo> list = BatchQueryUtils.queryAllByIdSize(
            (p, q) -> userDemoManager.queryUserDemoByIdSize(p, q),
            queryBo,
            idQueryBO);
    return UserDemoConverter.INSTANCE.covertUserDemoPoToBoList(list);
}

/**
 * 大数据量-Id区间查询全部
 *
 * @param queryBo queryBo
 * @return List<UserDemoBO>
 */
@Override
public List<UserDemoBO> queryAllUserDemoByIdSub(UserDemoQueryBO queryBo) {
    ImmutablePair<Long, Long> minAndMaxId = userDemoManager.queryMinAndMaxId(queryBo);
    Long minId = minAndMaxId.getLeft();
    Long maxId = minAndMaxId.getRight();
    IdQueryBO idQueryBO = new IdQueryBO(minId, maxId, 2L);
    List<UserDemo> list = BatchQueryUtils.queryAllByIdSub(
            (p, q) -> userDemoManager.queryUserDemoByIdSub(p, q),
            queryBo,
            idQueryBO);
    return UserDemoConverter.INSTANCE.covertUserDemoPoToBoList(list);
}



/**
 * 大数据量-线程池limit查询
 *
 * @param completionService completionService
 * @param query             query
 * @return List<Future < List < UserDemoExcel>>>
 */
@Override
public List<Future<List<UserDemoBO>>> queryAllUserDemoByPoolLimit(CompletionService<List<UserDemoBO>> completionService, UserDemoQueryBO query) {
    return BatchQueryUtils.queryAllByPoolLimit(completionService, p -> userDemoManager.queryUserDemoPage(p), query, 1);
}


/**
 * 大数据量-线程池根据Id区间查询
 *
 * @param completionService completionService
 * @param query             queryBO
 * @return List<Future < List < UserDemoExcel>>>
 */
@Override
public List<Future<List<UserDemoBO>>> queryAllUserDemoByPoolIdSub(CompletionService<List<UserDemoBO>> completionService, UserDemoQueryBO query) {
    ImmutablePair<Long, Long> minAndMaxId = userDemoManager.queryMinAndMaxId(query);
    Long minId = minAndMaxId.getLeft();
    Long maxId = minAndMaxId.getRight();
    IdQueryBO idQueryBO = new IdQueryBO(minId, maxId, 2L);
    return BatchQueryUtils.queryAllByPoolIdSub(completionService,
            (p, q) -> userDemoManager.queryUserDemoByIdSub(p, q),
            query,
            idQueryBO,
            UserDemoConverter.INSTANCE::covertUserDemoPoToBoList);
}

1、limit 分页查询


/**
 * 大数据量-分页查询全部
 *
 * @return {@link List<R>}
 */

public static <R> List<R> queryAllByLimit(LongFunction<PageBO<R>> function) {
    List<R> result = new ArrayList<>();
    long currentPageNo = 1;
    while (true) {
        PageBO<R> pageBo = function.apply(currentPageNo++);
        if (CollectionUtils.isEmpty(pageBo.getList())) {
            break;
        }
        result.addAll(pageBo.getList());
    }
    return result;
}

2、IdSize 分页查询


/**
 * 大数据量-IdSize查询全部
 *
 * @return {@link List<R>}
 */
public static <R> List<R> queryAllByIdSize(Function<IdQueryBO, List<R>> function, long pageSize) {

    IdQueryBO idQuery = new IdQueryBO(0L, pageSize);
    List<R> result = Lists.newArrayList();
    while (true) {
        List<R> dbList = function.apply(idQuery);
        if (CollectionUtils.isEmpty(dbList)) {
            break;
        }
        idQuery.setMinId(idQuery.getMaxId());
        result.addAll(dbList);
    }
    return result;
}

3、Id 区间查询全部

/**
 * 大数据量-Id区间查询全部
 *
 * @return {@link List<R>}
 */
public static <Q, R> List<R> queryAllByIdSub(Function<IdQueryBO, List<R>> function,
                                             IdQueryBO minMax) {
    List<R> result = Lists.newArrayList();
    Long minId = minMax.getMinId();
    Long maxId = minMax.getMaxId();
    Long size = minMax.getSize();
    for (long i = minId; i <= maxId; i = i + size) {
        long endId = Math.min(i + size, maxId);
        boolean maxEqualFlag = endId == maxId;
        IdQueryBO idQueryBO = new IdQueryBO(true, i, maxEqualFlag, endId, size);
        List<R> dbList = function.apply(idQueryBO);
        if (CollectionUtils.isEmpty(dbList)) {
            break;
        }
        result.addAll(dbList);
        if (maxEqualFlag) {
            break;
        }
    }
    return result;
}

4、线程池 limit 分页查询

/**
 * 大数据量-线程池limit查询
 *
 * @param executorService executorService
 * @param function        function
 * @param q               q
 * @param pageSize        pageSize
 */
public static <Q, T> List<Future<List<T>>> queryAllByPoolLimit(CompletionService<List<T>> executorService,
                                                               Function<PageQueryBO<Q>, PageBO<T>> function,
                                                               Q q,
                                                               long pageSize) {
    PageQueryBO<Q> pageQuery = new PageQueryBO<>(1L, 1L);
    pageQuery.setData(q);
    Long totalPage = function.apply(pageQuery).getTotalPage();
    List<Future<List<T>>> result = new ArrayList<>();
    for (long i = 1; i <= totalPage; i++) {
        PageQueryBO<Q> poolPageQuery = new PageQueryBO<>(i, pageSize);
        poolPageQuery.setData(q);
        Future<List<T>> future = executorService.submit(() -> {
            PageBO<T> pageBo = function.apply(poolPageQuery);
            return pageBo.getList();
        });
        result.add(future);
    }
    return result;
}

5、线程池 Id 区间查询

/**
 * 大数据量-线程池Id区间查询
 *
 * @param executorService 线程池
 * @param function        分页函数
 * @param query           查询条件
 * @param minMax          minMax 最小Id和最大Id
 * @param coverFunction   coverFunction 对象转化
 */
public static <Q, R, T> List<Future<List<T>>> queryAllByPoolIdSub(CompletionService<List<T>> executorService,
                                                                  BiFunction<IdQueryBO, Q, List<R>> function,
                                                                  Q query,
                                                                  IdQueryBO minMax,
                                                                  Function<List<R>, List<T>> coverFunction) {
    Long minId = minMax.getMinId();
    Long maxId = minMax.getMaxId();
    Long size = minMax.getSize();
    List<Future<List<T>>> result = new ArrayList<>();
    for (long i = minId; i <= maxId; i = i + size) {
        long endId = Math.min(i + size, maxId);
        boolean maxEqualFlag = endId == maxId;
        IdQueryBO idQueryBO = new IdQueryBO(true, i, maxEqualFlag, endId, size);
        Future<List<T>> future = executorService.submit(() -> {
            List<R> list = function.apply(idQueryBO, query);
            return coverFunction.apply(list);
        });
        result.add(future);
        if (maxEqualFlag) {
            break;
        }
    }
    return result;
}

ContactAuthor