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();
}
}
}