在某些业务场景中, 我们经常会对集合中的数据进行处理, Java8 提供了 Stream API 可以让我们很方便地处理集合中的数据, 例如, 分组, 过滤, 排序等, 但是每次处理数据的时候都要开流去处理, 所以我们可以对stream api进行一些简单的封装, 这样的话一些通用场景下就不需要写重复的逻辑了.
经过一阵子的努力, 我简单的封装了一个工具类, 目前工具类中功能大概有以下几个:
首先先准备两个函数, 用于判空, 一切都是从这两个函数开始的.
/**
* list判空
*
* @param list 集合
*/
private static void notEmptyCondition(List<?> list) {
if (list == null || list.size() == 0) throw new NullPointerException("这就有点不讲武德了, 给我个空我怎么处理呢.");
}
/**
* map 判空
*
* @param map map集合
*/
private static void notEmptyCondition(Map<?, ?> map) {
if (map == null || map.entrySet().size() == 0) throw new NullPointerException("这就有点不讲武德了, 给我个空我怎么处理呢.");
}
接着准备分组函数
/**
* 简单分组
*
* @param list 集合
* @param classifier 分组字段选择函数
* @param 输入类型
* @param Key的类型
* @return 最后返回Map
*/
public static <T, K> Map<K, List<T>> simpleGroupingBy(List<T> list, Function<? super T, ? extends K> classifier) {
notEmptyCondition(list);
return list.stream().collect(Collectors.groupingBy(classifier));
}
对分组后的结果进行排序
/**
* 基本排序操作, 这里约定了排序字段的选择必须是实现了Comparable接口的.
*
* @param list 集合
* @param desc 是否降序
* @param keySelect 排序字段选择函数
* @param 输入类型
*/
private static <T, U extends Comparable<U>> void sortList
(
List<T> list, boolean desc, Function<? super T, ? extends U> keySelect
) {
// 这里如果是降序的话, 就将List进行反转
if (desc) {
list.sort(Comparator.comparing(keySelect));
Collections.reverse(list); //反转List
} else {
list.sort(Comparator.comparing(keySelect));
}
}
/**
* 简单分组 + 排序字段的选择
*
* @param list 集合
* @param classifier 分组字段
* @param keySelect 排序字段选择
* @param desc 是否降序
* @param 输入类型
* @param key的类型
* @return 最后返回Map List为排序之后的List
*/
public static <T, K, C extends Comparable<C>> Map<K, List<T>> simpleGroupingBy
(
List<T> list, Function<? super T, ? extends K> classifier, boolean desc,
Function<? super T, ? extends C> keySelect
) {
notEmptyCondition(list);
sortList(list, desc, keySelect);
return list.stream().collect(Collectors.groupingBy(classifier));
}
public static void main(String[] args) {
ArrayList<TestUser> list = new ArrayList<TestUser>() {
{
add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
add(new TestUser("用户2", 1L, 110.0, 12, 20L));
add(new TestUser("用户3", 2L, 130.0, 13, 200L));
add(new TestUser("用户4", 2L, 150.0, 14, 20L));
}};
//根据TestUser的DeptId进行分组, 这里返回的Key为DeptId, value为List
Map<Long, List<TestUser>> result = FunctionalUtil.simpleGroupingBy(list, TestUser::getDeptId);
System.err.println("result = " + result);
//根据TestUser的DeptId进行分组, 并对List进行排序, 排序字段为TestUser的winningCount字段
Map<Long, List<TestUser>> result2 = FunctionalUtil.simpleGroupingBy(list, TestUser::getDeptId, true, TestUser::getWinningCount);
System.err.println("result2 = " + result2);
}
控制台打印的结果:
result = {1=[TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}, TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}], 2=[TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}]}
result2 = {1=[TestUser{username='用户2', deptId=1, score=110.0, count=12, winningCount=20}, TestUser{username='用户11111', deptId=1, score=120.0, count=11, winningCount=20}], 2=[TestUser{username='用户3', deptId=2, score=130.0, count=13, winningCount=200}, TestUser{username='用户4', deptId=2, score=150.0, count=14, winningCount=20}]}
在分组后从对象中选取字段进行返回
/**
* 可选返回字段函数式分组
*
* @param list 列表
* @param classifier 分组字段选择
* @param mappingFunction 返回字段
* @param 输入类型
* @param key类型
* @param 最后返回的元素类型
* @return 最后返回Map
*/
public static <T, K, U> Map<K, List<U>> customizingFieldGroupingBy
(
List<T> list, Function<? super T, ? extends K> classifier,
Function<? super T, ? extends U> mappingFunction
) {
notEmptyCondition(list);
return list.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(mappingFunction, Collectors.toList())));
}
排序结果: 和上面用的排序函数一致.
/**
* 可选返回字段函数式分组 + 排序字段选择
*
* @param list 列表
* @param classifier 分组字段选择
* @param mappingFunction 返回字段
* @param keySelect 排序字段选择
* @param desc 是否降序
* @param 输入类型
* @param key类型
* @param 最后返回的元素类型
* @return 最后返回Map
*/
public static <T, K, U, C extends Comparable<C>> Map<K, List<U>> customizingFieldGroupingBy
(
List<T> list, Function<? super T, ? extends K> classifier,
Function<? super T, ? extends U> mappingFunction, boolean desc,
Function<? super T, ? extends C> keySelect
) {
notEmptyCondition(list);
sortList(list, desc, keySelect);
return list.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(mappingFunction, Collectors.toList())));
}
public static void main(String[] args) {
ArrayList<TestUser> list = new ArrayList<TestUser>() {
{
add(new TestUser("用户11111", 1L, 120.0, 11, 20L));
add(new TestUser("用户2", 1L, 110.0, 12, 20L));
add(new TestUser("用户3", 2L, 130.0, 13, 200L));
add(new TestUser("用户4", 2L, 150.0, 14, 20L));
}};
//根据deptId字段进行分组, 选择score字段进行返回
Map<Long, List<Double>> resultMap = FunctionalUtil.customizingFieldGroupingBy(list, TestUser::getDeptId, TestUser::getScore);
System.err.println("resultMap = " + resultMap);
//根据deptId字段进行分组, 选择score字段进行返回, 按照score降序进行排序
Map<Long, List<Double>> resultMap2 = FunctionalUtil.customizingFieldGroupingBy(list, TestUser::getDeptId, TestUser::getScore, true, TestUser