集合对象结合CompletableFuture异步批次查询聚合

386 阅读1分钟

集合对象结合CompletableFuture异步批次查询聚合

import cn.hutool.core.collection.CollUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
​
/**
 * <p>
 *  集合分批次异步查询聚合
 * </p>
 * @author debug
 * @since 1949-10-01
 */
@Slf4j
public class PartitionCallListAsyncUtil {
​
    /**
     * 集合分批次异步查询聚合
     * @param dataList: 数据源类
     * @param size: 批次
     * @param executorService
     * @param function: 功能函数
     * @param <T>
     * @param <V>
     * @return
     */
    public static <T, V> List<V> partitionCallListAsync(List<T> dataList,
                                                         int size,
                                                         ExecutorService executorService,
                                                         Function<List<T>, List<V>> function) {
        if (CollUtil.isEmpty(dataList)) {
            return new ArrayList<>(0);
        }
        Preconditions.checkArgument(size > 0, "size must not be a minus");
        List<CompletableFuture<List<V>>> completableFutures = Lists.partition(dataList, size)
                .stream()
                .map(eachList -> {
                    return null == executorService ? CompletableFuture.supplyAsync(() -> function.apply(eachList)) : CompletableFuture.supplyAsync(() -> function.apply(eachList), executorService);
                })
                .collect(Collectors.toList());
        CompletableFuture<Void> allFinished = CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]));
        try {
            allFinished.get();
        } catch (Exception e) {
            log.error("PartitionCallListAsyncUtil.partitionCallListAsync get error - {}", e);
            throw new RuntimeException(e);
        }
        return completableFutures.stream()
                .map(CompletableFuture::join)
                .filter(CollUtil::isNotEmpty)
                .reduce(new ArrayList<>(), ((list1, list2) -> {
                    return collectionAggregation(list1, list2);
                }));
    }
​
    /**
     * 合并集合
     * @param sources
     * @param <V>
     * @return
     */
    private static <V> List<V> collectionAggregation(List<V> ... sources){
        List<V> result = new ArrayList<>();
        for (List<V> source : sources){
            if (CollUtil.isEmpty(source)){
                continue;
            }
            result.addAll(source);
        }
        return result;
    }
}