提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
collect 是一个归约操作,就像 reduce 一样可以接受各种做法作为参数,将流中的元素累积成一个汇总结果。具体的做法是通过定义新的Collector 接口来定义的。
一、使用方法
1.规约和汇总
public static void collectTest(){
List<Integer> numbers = Arrays.asList(1,2,3,4,5);
System.out.println(numbers.stream().count());//元素个数
Map<Boolean, List<Integer>> collect = numbers.stream().collect(groupingBy(i -> i % 2 == 0));//以奇偶数分组
System.out.println(collect.get(true));
System.out.println(numbers.stream().collect(maxBy(Comparator.comparingInt(i->i))));//最大值
System.out.println(numbers.stream().collect(summingInt(i->i)));//和
System.out.println(numbers.stream().collect(summarizingInt(i->i)));//一劳永逸,常用汇总数据
System.out.println(numbers.stream().map(i->i+"").collect(joining(",")));//连接字符串,并设置分隔符
}
5
[2, 4]
Optional[5]
15
IntSummaryStatistics{count=5, sum=15, min=1, average=3.000000, max=5}
1,2,3,4,5
2.分组
- 单级分组
按照一个属性对集合中的项目进行分组
实战:按照Dish的type进行分组
public class Dish {
String type;
String name;
int costs;
}
public static void groupTest() {
List<Dish> dishes=Arrays.asList(new Dish("fish","prawns",200),
new Dish("fish","salmon",200),
new Dish("meat","pock",20),
new Dish("meat","beef",30),
new Dish("meat","chicken",400),
new Dish("other","rice",50),
new Dish("other","fruit",60),
new Dish("other","pizza",700));//数据数组
Map<String,List<Dish>> dishByType=
dishes.stream().collect(Collectors.groupingBy(Dish::getType));//按照分类分组
for(Map.Entry type : dishByType.entrySet()){
String key=type.getKey().toString();
System.out.print(key+":");
List<Dish> dishes1=(List)type.getValue();
dishes1.forEach(o-> System.out.print(o.getName()+" "));
System.out.println();
}//遍历输出
}
输出结果
other:rice fruit pizza
fish:prawns salmon
meat:pock beef chicken
- 多级分组
按照多个属性对集合中的项目进行分组,在分组的基础上再进行分组。
实战:在按照type进行分组的基础上再按照花费进行分组
public enum Level { EXPENSIVE, NORMAL}//枚举来表示分级
Map<String,Map<Level,List<Dish> > > dishesByMuti=
dishes.stream().collect(Collectors.groupingBy(Dish::getType,//一级分组
Collectors.groupingBy(o ->{//二级分组
if(o.getCosts()>100) return Level.EXPENSIVE;
else return Level.NORMAL;
})));
for(Map.Entry type : dishesByMuti.entrySet()){//遍历
String key=type.getKey().toString();
System.out.print(key+": [");
Map<Level,List<Dish>> typeList=(Map)type.getValue();
for(Map.Entry level : typeList.entrySet()){
String levelName=level.getKey().toString();
List<Dish> list=(List) level.getValue();
System.out.print(levelName+"[");
list.forEach(o->{
System.out.print(o.getName()+":"+o.getCosts()+",");
});
System.out.print("]");
}
System.out.println(" ]");
}
输出结果
other: [ EXPENSIVE[pizza:700,]NORMAL[rice:50,fruit:60,] ]
fish: [ EXPENSIVE[prawns:200,salmon:200,] ]
meat: [ EXPENSIVE[chicken:400,]NORMAL[pock:20,beef:30,] ]
3.分区
分区是分组的特殊情况:由一个谓词(返回一个布尔值的函数)作为分类函数,它称分区函数。分区函数返回一个布尔值,这意味着得到的分组 Map 的键类型是 Boolean,于是它最多可以分为两组——true 是一组,false 是一组。
实战:按照菜品是否便宜分组
public static Boolean isCheap(Dish dish){
return dish.getCosts()<50;
}
Map<Boolean,List<Dish>> cheapMap=
dishes.stream().collect(Collectors.partitioningBy(Dish::isCheap));
for(Map.Entry type : cheapMap.entrySet()){
String key=type.getKey().toString();
System.out.print(key+":[ ");
List<Dish> dishes1=(List)type.getValue();
dishes1.forEach(o-> System.out.print(o.getName()+":"+o.getCosts()+","));
System.out.println(" ]");
}
输出结果
false:[ prawns:200,salmon:200,chicken:400,rice:50,fruit:60,pizza:700, ]
true:[ pock:20,beef:30, ]
其实也可以通过filter进行两次查询
//便宜的集合,不便宜的类似
Map<Boolean,List<Dish>> cheapMap=
dishes.stream().collect(Collectors.partitioningBy(Dish::isCheap));
List<Dish> cheapMap2=
dishes.stream().filter(Dish::isCheap).collect(toList());
cheapMap2.forEach(o->{
System.out.print(o.getName()+",");
});
pock
beef
其实分区和删选都能完成改需求,但分区的好处在于保留了分区函数返回 true 或 false 的两套流元素列表。
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。