您的位置:首页 > 编程语言 > Java开发

Java8新特性-Stream API 之Collector(三)

2018-08-15 00:40 489 查看

Collector与Collectors之间的关系

作为collect方法的参数,Collector是一个接口,它是一个可变的汇聚操作,将输入元素累计到一个可变的结果容器中;它会在所有元素都处理完毕后,将累积的结果转换为一个最终的表示(这是一个可选操作);

Collectors本身提供了关于Collector的常见汇聚实现,Collectors的内部类CollectorImpl实现了Collector接口,Collectors本身实际上是一个工厂。

Collectors提供哪些方法

工厂方法名 返回类型 作用
toList List<T> List集合
toSet Set<T> Set<T>,去重
maxBy Option<T> Optional<T>
groupingBy Map<key,List> 元素分组
summingInt Integer 所有元素某个属性求和
averagingInt Integer 所有元素某个属性的平均值
summarizingInt IntSummaryStatistics 一次获取多个值, count, sum, min, max, average
joining String 将所有的元素的某个属性拼接成字符串
reducing 累加的类型 累加计算
collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果应用转换函数
partitioningBy Map<Boolean,List<T>> 根据对流中每个项目应用谓词的结果来对项目进行分区
collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果应用转换函数
public class CollectorsDemo {

public static void main(String[] args) {

List<Dish> menu = Arrays.asList(
new Dish("pork", false, 800, Dish.Type.MEAT),
new Dish("beef", false, 700, Dish.Type.MEAT),
new Dish("chicken", false, 400, Dish.Type.MEAT),
new Dish("french fries", true, 530, Dish.Type.OTHER),
new Dish("rice", true, 350, Dish.Type.OTHER),
new Dish("season fruit", true, 120, Dish.Type.OTHER),
new Dish("pizza", true, 550, Dish.Type.OTHER),
new Dish("prawns", false, 300, Dish.Type.FISH),
new Dish("salmon", false, 450, Dish.Type.FISH));

//maxby  test  筛选出最大的元素
Comparator<Dish> dishCaloriesComparator =
comparingInt(Dish::getCalories);
menu.stream().collect(maxBy(dishCaloriesComparator))
.ifPresent(a -> System.out.println("max calories --->" + a.getCalories()));

//groupingby test  将元素的某个属性提取出来进行分组
Map<Dish.Type, List<Dish>> map = menu.stream().collect(groupingBy(Dish::getType));
for (Map.Entry<Dish.Type, List<Dish>> entry : map.entrySet()) {
System.out.println(entry.getKey() + "---" + entry.getValue().size());
}

//summingInt test  计算所有元素的和
int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

//averagingInt test  计算所有元素的平均值
double averageCalories = menu.stream().collect(averagingInt(Dish::getCalories));

//summarizingInt test  一次获取多个值, count, sum, min, max, average
IntSummaryStatistics menuStatistics =
menu.stream().collect(summarizingInt(Dish::getCalories));
System.out.println(menuStatistics.toString());

//join  test  joining(",") 可以指定连接符,避免拼接字符串,还要对最后一个元素进行特殊处理
// 如:每个元素拼接 element+"," 最后去掉最后一个","号
String shortMenu = menu.stream().map(Dish::getName).collect(joining(","));
System.out.println("join test --->" + shortMenu);

//reducing 实现
menu.stream().collect(Collectors.reducing(
0,               //初始值
Dish::getCalories,      //转换函数
(a, b) -> a + b));           //累计函数
menu.stream().collect(Collectors.reducing(0, Dish::getCalories, Integer::sum));

//获取热量最高的值,默认值有可能为空所以返回Optional,
menu.stream().collect(Collectors.reducing(
(d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2))
.ifPresent(a -> System.out.println("max calories---" + a.getCalories()));

// 根据需要修改key,修改lambda表达式里面的逻辑
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(
groupingBy(dish -> {
return getLevel(dish);
}));

//二级分组
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel =
menu.stream().collect(
groupingBy(Dish::getType,
groupingBy(dish -> {
return getLevel(dish);
})
)
);

//获取每种类型中热量最高的dish
Map<Dish.Type, Optional<Dish>> mostCaloricByType =
menu.stream()
.collect(groupingBy(Dish::getType,
maxBy(comparingInt(Dish::getCalories))));

//将optional直接转换要用collectingAndThen
Map<Dish.Type, Dish> mostCaloricDish =
menu.stream()
.collect(groupingBy(Dish::getType,
Collectors.collectingAndThen(
maxBy(comparingInt(Dish::getCalories)),
Optional::get)));

//格式化value的方法
Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType =
menu.stream().collect(
groupingBy(Dish::getType, Collectors.mapping(
dish -> {
return getLevel(dish);
},
Collectors.toSet())));
//分区partitioningBy test,传入谓词
Map<Boolean, List<Dish>> partitionedMenu =
menu.stream().collect(Collectors.partitioningBy(Dish::isVegetarian));

//只返回符合条件的
List<Dish> vegetarianDishes =
menu.stream().filter(Dish::isVegetarian).collect(Collectors.toList());
System.out.println(vegetarianDishes.size());

}

public enum CaloricLevel {DIET, NORMAL, FAT}

public static CaloricLevel getLevel(Dish dish){
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: