当前位置: 首页 > article >正文

lambda strem流表达式处理工具

一个通用的lambda stream流处理工具, 包含了工作中绝大部分场景常用的使用方式

import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;

/**
 * lambda strem流表达式处理工具
 *
 * @Date 2021/6/3 10:59 下午
 */
public class LambdaUtils {

    /**
     * 默认分隔符
     */
    public static final String DEFAULT_SPLIT_CHAR = ",";

    /**
     * 默认连接符
     */
    public static final String DEFAULT_CONNECTOR_CHAR = "&&";

    /**
     * 查找list中的第一个
     *
     * @param datas list数据
     * @param <T>   list中的理性
     * @return 找到的第一个,可能为空
     */
    public static <T> T findFirstOrNull(List<T> datas) {
        return findFirstOrDefault(datas, null);
    }

    public static <T> T findFirstOrDefault(List<T> datas, T t) {
        return Optional.ofNullable(datas).flatMap(e -> e.stream().findFirst()).orElse(t);
    }

    /**
     * 返回null或者默认值
     */
    public static <T> T getOrDefault(T t, T def) {
        return Optional.ofNullable(t).orElse(def);
    }

    /**
     * 展平嵌套列表的工具方法,将嵌套list转换为单层list
     *
     * @param listOfLists 嵌套的list
     * @param <T>         list中的类型
     * @return 展平之后的list
     */
    public static <T> List<T> flattenList(List<List<T>> listOfLists) {
        return listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
    }

    /**
     * 基于某个键值进行去重的工具方法, 使用map去重, 丢失了原来的顺序
     *
     * @param list         参数list
     * @param keyExtractor 获取键值的函数
     * @param <T>          list中数据的类型
     * @param <R>          去重字段的类型
     * @return 去重之后的list
     */
    public static <T, R> List<T> distinctByKey(List<T> list, Function<? super T, R> keyExtractor) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>(0);
        }
        return new ArrayList<>(
                list.stream().collect(Collectors.toMap(keyExtractor, Function.identity(), (oo, no) -> oo)).values());
    }

    /**
     * 保持原有的顺序,去重
     */
    public static <T, R> List<T> distinctByKeySort(List<T> list, Function<? super T, R> keyExtractor) {
        if (list == null) {
            return new ArrayList<>(0);
        }

        Set<R> seen = new LinkedHashSet<>(list.size());
        return list.stream().filter(element -> seen.add(keyExtractor.apply(element))).collect(Collectors.toList());
    }

    /**
     * 根据给定的判断将列表分区为两个子列表的工具方法, 满足判断条件的根据true获取结果, 不满足判断条件的根据false获取结果
     *
     * @param list      需要被分区的list
     * @param predicate 分区的条件
     * @param <T>       list中数据的类型
     * @return 分区后的map
     */
    public static <T> Map<Boolean, List<T>> partitionBy(List<T> list, Predicate<T> predicate) {
        return Optional.ofNullable(list).map(items -> items.stream().collect(Collectors.partitioningBy(predicate))).orElse(new HashMap<>(0));
    }

    /**
     * 根据某个条件删除集合中的元素, 条件为true则删除
     *
     * @param collection 集合对象
     * @param predicate  删除条件
     * @param <T>        集合中的数据类型
     */
    public static <T> void removeIf(Collection<T> collection, Predicate<T> predicate) {
        if (collection != null) {
            collection.removeIf(predicate);
        }
    }

    public static <T> void dealAndConsumer(List<T> datas, Consumer<T> consumer) {
        Optional.ofNullable(datas).ifPresent(list -> list.forEach(consumer));
    }

    /**
     * 用func处理list中的每一条数据, 并收集到list中返回
     *
     * @param datas list数据
     * @param func  处理每条数据的函数
     * @param <T>   datas的数据类型
     * @param <R>   func处理后的数据类型
     */
    public static <T, R> List<R> dealAndtoList(List<T> datas, Function<T, R> func) {
        return Optional.ofNullable(datas).map(list -> list.stream().map(func).collect(Collectors.toList()))
                .orElse(new ArrayList<>(0));
    }

    public static <T, R> List<R> dealAndtoFlattenList(List<T> datas, Function<T, List<R>> func) {
        return Optional.ofNullable(datas).map(list -> list.stream().map(func).flatMap(List::stream).collect(Collectors.toList()))
                .orElse(new ArrayList<>(0));
    }

    /**
     * 处理嵌套list, func函数用来处理外部list获得嵌套的list, nestedFunc函数用来生成嵌套list的返回结果
     *
     * @param datas 原始数据列表,可以是任何类型
     * @param func 函数,用于将列表中的每个元素转换为另一个列表
     * @param nestedFunc 嵌套函数,用于进一步处理转换后的列表中的每个元素
     * @return 处理后的列表,包含通过嵌套函数处理过的元素
     */
    public static <OT, NT, NR> List<NR> dealAndNestedFlattenList(List<OT> datas, Function<OT, List<NT>> func, Function<NT, NR> nestedFunc) {
        // 使用Optional处理可能的null输入,确保在输入为null时返回空列表而不是抛出异常
        return Optional.ofNullable(datas)
                // 将列表中的每个元素使用提供的函数进行转换,然后通过flatMap进行扁平化处理
                .map(list -> list.stream().map(func).flatMap(List::stream)
                        // 对扁平化后的每个元素应用嵌套函数,并收集到一个新的列表中
                        .map(nestedFunc).collect(Collectors.toList()))
                // 如果输入为null,返回空列表
                .orElse(new ArrayList<>(0));
    }

    /**
     * 处理嵌套list, func函数用来处理外部list获得嵌套的list, outReturnFunc函数用来生成外部list返回的结果, nestedFunc函数用来生成嵌套list的返回结果
     * @param datas 数据源
     * @param func  获得嵌套list的函数
     * @param outReturnFunc 获得外部list结果的函数
     * @param nestedFunc    获得内部list结果的函数
     * @return  一个pair对象, 第一个元素是外部list的结果, 第二个元素是内部list的结果
     * @param <OT>   外层list的元素类型
     * @param <NT>  内部list的元素类型
     * @param <OR>  外部list的返回结果
     * @param <NR>  内部list的返回结果
     */
    public static <OT, NT, OR, NR> Pair<List<OR>, List<NR>> dealAndNestedFlattenList(List<OT> datas, Function<OT, List<NT>> func, Function<OT, OR> outReturnFunc, Function<NT, NR> nestedFunc) {
        if (CollectionUtils.isEmpty(datas)) {
            return Pair.of(new ArrayList<>(0), new ArrayList<>(0));
        }
        List<OR> outResult = new ArrayList<>(datas.size());
        List<NR> innserResult = new ArrayList<>();
        for (OT data : datas) {
            // 外部list返回的结果
            OR outRt = outReturnFunc.apply(data);
            outResult.add(outRt);
            // 内部list
            List<NT> innerList = func.apply(data);
            if (CollectionUtils.isEmpty(innerList)) {
                continue;
            }
            for (NT r : innerList) {
                // 内部list返回的结果
                NR innerRt = nestedFunc.apply(r);
                innserResult.add(innerRt);
            }
        }
        return Pair.of(outResult, innserResult);
    }


    /**
     * 将datas中的数据按照func处理,返回处理后的数据集合,然后将该集合给consumer消费
     *
     * @param datas    list数据
     * @param func     处理每条数据的函数
     * @param consumer 消费func处理后的数据集
     * @param <T>      datas的数据类型
     * @param <R>      func处理后的数据类型
     */
    public static <T, R> void dealAndConsumer(List<T> datas, Function<T, R> func, Consumer<List<R>> consumer) {
        Optional.ofNullable(datas).map(list -> list.stream().map(func).collect(Collectors.toList()))
                .ifPresent(consumer);
    }

    /**
     * 用func处理list中的每条数据,然后给consumer消费;如果func处理的某条数据为空,那么该条数据不会被consumer消费
     */
    public static <T, R> void dealAndConsumerWithoutNull(List<T> datas, Function<T, R> func,
                                                         Consumer<List<R>> consumer) {
        Optional.ofNullable(datas)
                .map(list -> list.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList()))
                .ifPresent(consumer);
    }

    /**
     * 用func处理set中的每条数据,然后给consumer消费;如果处理的为空,那么不会被consumer消费
     */
    public static <T, R> void dealAndConsumerWithoutNull(Set<T> datas, Function<T, R> func, Consumer<Set<R>> consumer) {
        Optional.ofNullable(datas)
                .map(set -> set.stream().map(func).filter(Objects::nonNull).collect(Collectors.toSet()))
                .ifPresent(consumer);
    }

    /**
     * list转map,转换后的key不会重复(如果有key冲突, 前者覆盖后者)
     *
     * @param datas   待转换的list
     * @param keyFunc 生成key的函数,例如 Class::getName
     * @param <T>     list集合中的元素类型
     * @param <R>     生成的map的key的类型
     * @return 返回生成的map对象
     */
    public static <T, R> Map<R, T> list2Map(List<T> datas, Function<T, R> keyFunc) {
        return Optional.ofNullable(datas)
                .map(as -> as.stream().collect(Collectors.toMap(keyFunc, Function.identity(), (eo, no) -> eo)))
                .orElse(new HashMap<>(0));
    }

    /**
     * list转map,转换后的key不会重复(如果有key冲突, 前者覆盖后者); 注意: 如果valFunc得到的结果是null,将会NPE异常
     *
     * @param datas   待转换的list
     * @param keyFunc 生成key的函数,例如 Class::getName
     * @param valFunc 生成value的函数,例如 Class::getName
     * @param <T>     list集合中的元素类型
     * @param <R>     生成的map的key的类型
     * @param <V>     生成的map的value的类型
     * @return 返回生成的map对象
     */
    public static <T, R, V> Map<R, V> list2Map(List<T> datas, Function<T, R> keyFunc, Function<T, V> valFunc) {
        return Optional.ofNullable(datas)
                .map(as -> as.stream().collect(Collectors.toMap(keyFunc, valFunc, (eo, no) -> no)))
                .orElse(new HashMap<>(0));
    }

    /**
     * 根据两个个key值生成map
     */
    public static <T> Map<String, T> list2MapMultiKey(List<T> datas, Function<T, Object> keyFunc, Function<T, Object> keyFunc2) {
        return Optional.ofNullable(datas)
                .map(as -> as.stream().collect(Collectors.toMap(e -> keyFunc.apply(e) + DEFAULT_CONNECTOR_CHAR + keyFunc2.apply(e), Function.identity(), (eo, no) -> no)))
                .orElse(new HashMap<>(0));
    }


    /**
     * 过滤掉list中的null元素
     *
     * @param datas 待过滤的list
     * @param <T>   list中的元素类型
     * @return 去掉null元素的之后的list结合
     */
    public static <T> List<T> filterNull(List<T> datas) {
        return Optional.ofNullable(datas)
                .map(list -> list.stream().filter(Objects::nonNull).collect(Collectors.toList()))
                .orElse(new ArrayList<>(0));
    }

    /**
     * 过滤list中的元素
     *
     * @param datas     待过滤的list
     * @param predicate 过滤条件
     * @param <T>       list中的元素类型
     * @return 过滤后的list
     */
    public static <T> List<T> filter(List<T> datas, Predicate<T> predicate) {
        return Optional.ofNullable(datas).map(list -> list.stream().filter(predicate).collect(Collectors.toList()))
                .orElse(new ArrayList<>(0));
    }

    public static <T> boolean anyMatch(List<T> datas, Predicate<T> predicate) {
        return Optional.ofNullable(datas).map(list -> list.stream().anyMatch(predicate)).orElse(false);
    }

    public static <T> boolean allMatch(List<T> datas, Predicate<T> predicate) {
        return Optional.ofNullable(datas).map(list -> list.stream().allMatch(predicate)).orElse(false);
    }

    public static <T> boolean noneMatch(List<T> datas, Predicate<T> predicate) {
        return Optional.ofNullable(datas).map(list -> list.stream().noneMatch(predicate)).orElse(false);
    }

    /**
     * list转string,以,分割
     *
     * @param datas list数据
     * @param func  处理list中每个元素的函数
     * @param <T>   list中的数据类型
     * @return 处理后的string, 如果datas为空,默认返回null
     */
    public static <T> String list2Str(List<T> datas, Function<T, String> func) {
        return list2StrWithSeparator(datas, func, DEFAULT_SPLIT_CHAR);
    }

    /**
     * list转string,自定义分隔符
     *
     * @param datas     list数据
     * @param func      处理list中每个元素的函数
     * @param separator 分隔符
     * @param <T>       list中的数据类型
     * @return 处理后的string, 如果datas为空,默认返回null
     */
    public static <T> String list2StrWithSeparator(List<T> datas, Function<T, String> func, String separator) {
        return Optional.ofNullable(datas).map(list -> list.stream().map(func).collect(Collectors.joining(separator)))
                .orElse(null);
    }

    /**
     * map转list
     *
     * @param datas map对象
     * @param func  处理map中每一对元素的函数
     * @param <K>   key的类型
     * @param <V>   value的类型
     * @param <R>   返回的list中元素类型
     * @return 转换后的list对象
     */
    public static <K, V, R> List<R> map2List(Map<K, V> datas, BiFunction<K, V, R> func) {
        return Optional.ofNullable(datas).map(
                        m -> m.entrySet().stream().map(me -> func.apply(me.getKey(), me.getValue())).collect(Collectors.toList()))
                .orElse(null);
    }

    /**
     * 分组, 根据指定的key, 返回同一组实体对象
     *
     * @param list    集合数据
     * @param keyFunc 获取key的方法
     * @param <K>     key的类型
     * @param <T>     集合中的数据类型
     * @return 转换后的map或者不可变map
     */
    public static <K, T> Map<K, List<T>> groupBy(List<T> list, Function<T, K> keyFunc) {
        return Optional.ofNullable(list).map(tl -> tl.stream().collect(Collectors.groupingBy(keyFunc)))
                .orElse(new HashMap<>(0));
    }

    /**
     * 根据某个 key 进行分组,并将两个不同类型的值分别放入两个 List 中,返回 Map<K, Pair<List<V1>, List<V2>>>
     *
     * @param items        输入的列表
     * @param keyMapper    用于获取 key 的方法
     * @param value1Mapper 用于获取第一个 List 值的映射方法
     * @param value2Mapper 用于获取第二个 List 值的映射方法
     * @param <K>          分组的 key 类型
     * @param <V>          输入的列表项类型
     * @param <V1>         第一个 List 的值类型
     * @param <V2>         第二个 List 的值类型
     * @return Map<K, Pair < List < V1>, List<V2>>> 格式的数据
     */
    public static <K, V, V1, V2> Map<K, Pair<List<V1>, List<V2>>> groupBy(List<V> items, Function<V, K> keyMapper,
                                                                          Function<V, V1> value1Mapper, Function<V, V2> value2Mapper) {

        // 创建一个 Map,用于存储结果
        Map<K, Pair<List<V1>, List<V2>>> resultMap = new HashMap<>();

        // 遍历输入的 items 列表
        for (V item : items) {
            // 通过 keyMapper 获取分组 key
            K key = keyMapper.apply(item);

            // 使用 computeIfAbsent 确保每个 key 对应一个 Pair<List<V1>, List<V2>>
            Pair<List<V1>, List<V2>> pair =
                    resultMap.computeIfAbsent(key, k -> Pair.of(new ArrayList<>(), new ArrayList<>()));

            // 将第一个值加入 Pair 的第一个 List 中
            pair.getKey().add(value1Mapper.apply(item));

            // 将第二个值加入 Pair 的第二个 List 中
            pair.getValue().add(value2Mapper.apply(item));
        }

        // 返回结果 Map
        return resultMap;
    }

    /**
     * 两层次分组的通用方法,生成 Map<K1, Map<K2, V2>> 格式的结果 根据 keyMapper1 和 keyMapper2 分别对列表中的元素进行分组,并将元素映射到 valueMapper 中,最后使用
     * resultCollector 收集结果
     *
     * @param items       输入的列表
     * @param keyMapper1  第一层分组的 key 提取器
     * @param keyMapper2  第二层分组的 key 提取器
     * @param valueMapper 用于将列表项映射成最终的值
     * @param <V>         输入的列表项类型
     * @param <K1>        第一层分组的 key 类型
     * @param <K2>        第二层分组的 key 类型
     * @param <V2>        第二次分组的值类型
     * @param <V3>        最终映射的值类型
     * @return Map<K1, Map < K2, V2>> 分组后的结果
     */
    public static <V, K1, K2, V2, V3> Map<K1, Map<K2, V3>> multiLevelGroupBy(List<V> items, Function<V, K1> keyMapper1,
                                                                             Function<V, K2> keyMapper2, Function<V, V2> valueMapper, Collector<V2, ?, V3> resultCollector) {

        if (items == null) {
            return new HashMap<>(0);
        }
        return items.stream().collect(Collectors.groupingBy(keyMapper1,
                Collectors.groupingBy(keyMapper2, Collectors.mapping(valueMapper, resultCollector))));
    }

    /**
     * 多个key组成对象的map; 例如 {k1&&k2, [v1,v2]},{k1&&k3, [v1,v2]}
     */
    public static <T, K> Map<String, List<T>> groupByMultiKey(List<T> list, Function<T, K>... keyFuncs) {
        if (list == null) {
            return new HashMap<>(0);
        }
        if (keyFuncs == null || keyFuncs.length == 0) {
            return new HashMap<>(0);
        }
        return list.stream().collect(Collectors.groupingBy(e -> Stream.of(keyFuncs).map(keyFunc -> keyFunc.apply(e) + "").collect(Collectors.joining(DEFAULT_CONNECTOR_CHAR))));
    }

    /**
     * 先对每一条元素执行consumer操作 然后根据指定的key分组
     *
     * @param list     待处理的list
     * @param consumer 执行的consumer
     * @param keyFunc  获取key的方法
     * @param <K>      key的类型
     * @param <T>      集合中的数据类型
     * @return 转换后的map或者不可变map
     */
    public static <K, T> Map<K, List<T>> consumerAndGroupBy(List<T> list, Consumer<T> consumer,
                                                            Function<T, K> keyFunc) {
        return Optional.ofNullable(list)
                .map(tl -> tl.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(item -> {
                    consumer.accept(item); // 执行副作用操作
                    return item;
                }, Collectors.toList())))).orElse(new HashMap<>(0));
    }

    /**
     * 分组求和
     *
     * @param list        待处理的list
     * @param keyFunc     获取key的方法
     * @param sumFieldKey 需要求和的字段
     * @param <K>         分组字段的类型
     * @param <T>         数据类型
     * @return 分组求和的结果
     */
    public static <K, T> Map<K, BigDecimal> groupAndSum(List<T> list, Function<T, K> keyFunc, Function<T, BigDecimal> sumFieldKey) {
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>(0);
        }
        return list.stream().collect(Collectors.groupingBy(keyFunc,
                Collectors.reducing(BigDecimal.ZERO, sumFieldKey, BigDecimal::add)));
    }

    /**
     * 分组, 根据指定的key, 返回同一组value
     *
     * @param list    集合数据
     * @param keyFunc 获取key的方法
     * @param valFunc 获取value的方法
     * @param <K>     key的类型
     * @param <T>     集合中的数据类型
     * @param <V>     value的类型
     * @return
     */
    public static <K, T, V> Map<K, List<V>> groupBy(List<T> list, Function<T, K> keyFunc, Function<T, V> valFunc) {
        return Optional.ofNullable(list).map(
                        tl -> tl.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valFunc, Collectors.toList()))))
                .orElse(new HashMap<>(0));
    }

    /**
     * 嵌套分组, 将list集合中的数据按照某个键值进行分组,再按照另一个键值进行分组,返回嵌套的map对象, 类似与group by k1,k2
     *
     * @param list          需要分组的集合
     * @param keyExtractor1 分组键值1
     * @param keyExtractor2 分组键值2
     * @param <T>           集合中元素类型
     * @param <K1>          第一层分组的键值类型
     * @param <K2>          第二层分组的键值类型
     * @return
     */
    public static <T, K1, K2> Map<K1, Map<K2, List<T>>> nestedGroupBy(List<T> list, Function<T, K1> keyExtractor1,
                                                                      Function<T, K2> keyExtractor2) {
        return Optional.ofNullable(list)
                .map(tl -> tl.stream().collect(Collectors.groupingBy(keyExtractor1, Collectors.groupingBy(keyExtractor2))))
                .orElse(new HashMap<>(0));
    }

    /**
     * 嵌套分组, 将list集合中的数据按照某个键值进行分组,再按照另一个键值进行分组,再按照另一个键值进行分组,返回嵌套的map对象, 类似与group by k1,k2,k3
     *
     * @param list        需要分组的集合
     * @param classifier1 第一层分组的键值类型
     * @param classifier2 第二层分组的键值类型
     * @param classifier3 第三层分组的键值类型
     */
    public static <T, K1, K2, K3> Map<K1, Map<K2, Map<K3, List<T>>>> nestedGroupingBy(List<T> list,
                                                                                      Function<T, K1> classifier1, Function<T, K2> classifier2, Function<T, K3> classifier3) {

        return Optional.ofNullable(list).map(tl -> tl.stream().collect(
                        Collectors.groupingBy(classifier1, Collectors.groupingBy(classifier2, Collectors.groupingBy(classifier3)))))
                .orElse(new HashMap<>(0));
    }

    /**
     * bigDecimal求和, 过滤掉了空值
     */
    public static BigDecimal sumBigDecimal(List<BigDecimal> numbers) {
        return Optional.ofNullable(numbers)
                .map(list -> list.stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add))
                .orElse(BigDecimal.ZERO);
    }

    /**
     * 根据key分组求和
     */
    public static <T> BigDecimal sumBigDecimalByKey(List<T> list, Function<T, BigDecimal> keyExtractor) {
        return Optional.ofNullable(list)
                .map(tl -> tl.stream().map(keyExtractor).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add))
                .orElse(BigDecimal.ZERO);
    }

    /**
     * 按照对象的某个属性进行升序排序
     *
     * @param list         待排序的对象列表
     * @param keyExtractor 提取排序键的函数
     * @param <T>          对象类型
     * @param <U>          排序键类型
     */
    public static <T, U extends Comparable<? super U>> void sortBy(List<T> list, Function<T, U> keyExtractor) {
        Optional.ofNullable(list).ifPresent(tl -> tl.sort(Comparator.comparing(keyExtractor)));
    }

    /**
     * 按照对象的某个属性进行降序排序
     *
     * @param list         待排序的对象列表
     * @param keyExtractor 提取排序键的函数
     * @param <T>          对象类型
     * @param <U>          排序键类型
     */
    public static <T, U extends Comparable<? super U>> void sortByDesc(List<T> list, Function<T, U> keyExtractor) {
        Optional.ofNullable(list).ifPresent(tl -> tl.sort(Comparator.comparing(keyExtractor).reversed()));
    }

    /**
     * 多属性排序:支持多条件的排序,按照第一个属性排序,然后是第二个属性,以此类推
     *
     * @param list          待排序的对象列表
     * @param keyExtractors 排序键提取函数列表
     * @param <T>           对象类型
     */
    @SafeVarargs
    @SuppressWarnings("unchecked")
    public static <T> void sortByMulti(List<T> list, Function<T, ? extends Comparable<?>>... keyExtractors) {
        if (list == null || keyExtractors.length == 0) {
            return;
        }
        Comparator<T> comparator = null;
        for (Function<T, ? extends Comparable<?>> keyExtractor : keyExtractors) {
            if (comparator == null) {
                comparator = Comparator.comparing((Function<T, Comparable<Object>>) keyExtractor);
            } else {
                comparator = comparator.thenComparing((Function<T, Comparable<Object>>) keyExtractor);
            }
        }

        list.sort(comparator);
    }

    /**
     * 多属性降序排序:支持多条件的降序排序,按照第一个属性降序排序,然后是第二个属性,以此类推
     *
     * @param list          待排序的对象列表
     * @param keyExtractors 排序键提取函数列表
     * @param <T>           对象类型
     */
    @SafeVarargs
    @SuppressWarnings("unchecked")
    public static <T> void sortByMultiDesc(List<T> list, Function<T, ? extends Comparable<?>>... keyExtractors) {
        if (list == null || keyExtractors.length == 0) {
            return;
        }
        Comparator<T> comparator = null;
        for (Function<T, ? extends Comparable<?>> keyExtractor : keyExtractors) {
            if (comparator == null) {
                comparator =
                        Comparator.comparing((Function<T, Comparable<Object>>) keyExtractor, Comparator.reverseOrder());
            } else {
                comparator =
                        comparator.thenComparing((Function<T, Comparable<Object>>) keyExtractor, Comparator.reverseOrder());
            }
        }

        list.sort(comparator);
    }

    /**
     * 多属性排序:支持多条件的排序, 可以指定某个条件升序还是降序, 按照第一个属性排序,然后是第二个属性,以此类推
     */
    public static <T> void sortByRules(List<T> list,
                                       Pair<Function<T, ? extends Comparable<?>>, Boolean>... keyExtractors) {
        if (list == null || keyExtractors.length == 0) {
            return;
        }
        Comparator<T> comparator = null;

        for (Pair<Function<T, ? extends Comparable<?>>, Boolean> pair : keyExtractors) {
            if (comparator == null) {
                comparator =
                        Comparator.comparing((Function<T, Comparable<Object>>) pair.getLeft(), getSortRule(pair.getRight()));
            } else {
                comparator = comparator.thenComparing((Function<T, Comparable<Object>>) pair.getLeft(),
                        getSortRule(pair.getRight()));
            }
        }

        list.sort(comparator);
    }

    private static <T extends Comparable<? super T>> Comparator<T> getSortRule(boolean asc) {
        if (asc) {
            return Comparator.naturalOrder();
        } else {
            return Comparator.reverseOrder();
        }
    }
}

http://www.kler.cn/a/421037.html

相关文章:

  • ⭐Java---反射--获取类信息⭐
  • 【算法】【优选算法】位运算(下)
  • JAVA设计模式,动态代理模式
  • 6.824/6.5840(2024)环境配置wsl2+vscode
  • Rust循环引用与多线程并发
  • C#:时间与时间戳的转换
  • 第10章 大模型的有害性(下)
  • 初始化webpack应用示例
  • 基于python的某音乐网站热门歌曲的采集与分析,包括聚类和Lda主题分析
  • QT5.14 QML串口助手
  • Docker快速部署RabbitMq
  • 【Vue3】Vue3与React的路由管理对比:详细解析与实战案例!
  • WPF+LibVLC开发播放器-LibVLC在C#中的使用
  • 高速定向广播声光预警系统赋能高速安全管控
  • 代码随想录算法训练营第三十五天 | 01背包问题(二维,一维) | 416. 分割等和子集 | 1049.最后一块石头的重量II
  • JVM 为什么需要类加载机制?深入浅出 JVM 类加载原理
  • GCP : Virtual Private Cloud - 如何构建Nat Gateway
  • 云原生后端:解锁高效可扩展应用的魔法世界
  • Redis自学之路—高级特性(实现消息队列)(七)
  • 安装 pytorch lighting
  • 简单无注册中心本地ip轮训网关实现
  • 【合作原创】使用Termux搭建可以使用的生产力环境(二)
  • (笔记)vue3引入Element-plus
  • 【网络】协议与网络传输
  • 【导航查询】.NET开源 ORM 框架 SqlSugar 系列
  • 联想YOGA Pro 14s至尊版电脑找不到独立显卡(N卡)问题,也无法安装驱动的问题