StreamAPI
最近开发用上了
Java8
的StreamAPI,(咋现在才用?嗯哼,项目需要)自己也不怎么会,来总结一波吧!别认为好抽象!!!干他就完事
一.StreamAPI介绍
就是用来处理集合的数据 其实到后面会发现和SQL的语句是差不多的~哈哈?你不信?往下面看
Stream
:英文翻译叫做流
举个粟子:
Stream
相当于一条河流,数据相当于里面的水,这条河流里面的水你要饮用还是其他操作叫做Stream
的执行数据操作,从而达到你要的目的(比如达成饮用水的目的),在计算机中就是处理达成你要的结果
注意!
Stream
不会自己存储元素- 不会改变源对象,只是返回含有结果的一个新
Stream
- 延迟执行,在要结果的时候才执行(有点像懒汉模式)
二.流操作的过程
主要就是从生到死周期
- 创建Stream:就是从一个数组或者集合拿取数据(相当于找到水源地)
//主要两种创建方式:
1.Steam()
2.parallelStream() //这个主要返回并行流
//eg:
List<String> list=new ArrayList<>();
Stream<String> s1=list.stream();//
===========================================
//值创建流 Stream.of() 静态方法显示创建
Stream<String> s=Stream.of("a","s","ddddd");
s.forEach(System.out::println);
==============================================
//创建无限流
Stream.iterate() 和 Stream.generate()两个方法
//举例 迭代
Steam<Integer> s=Stream.iterate(0,(x)->x>>1);
s.limit(10).forEach(System.out::println);
//举例 生成
Stream.generate(()->Math.random().limit(6)
forEach(System.out::println));
- **中间逻辑操作:**就相当于SQL语句中执行条件,处理达到你要的结果和业务数据(比如你要取水去做饮用水啊中间是不是要净化啥的操作)
看下面的主题,太多了,但也是重点
- **结束:**就是终止条件,写结果返回语句,不能无休止啊
三.中间操作
在
终止操作时
才会一次性全部处理,就是要到开学了,小学生才会用功写完全部作业~哈哈
filter,limit,skip,distinct
1.筛选切片
Filter:接受
Lambda
,进行过滤操作,排除一些不需要的元素
// (1)filter——接收 Lambda , 从流中排除某些元素。
@Test
public void testFilter() {
//这里加入了终止操作 ,不然中间操作一系列不会执行
//中间操作只有在碰到终止操作才会执行
emps.stream()
.filter((e)->e.getAge()>18) //过滤只要年龄大于18 的
.forEach(System.out::println);//终止操作
}
limit(n):截取指定n个以内数量的元素
// (2)limit——截断流,使其元素不超过给定数量。
@Test
public void testLimit() {
emps.stream()
.filter((e)->e.getAge()>8)
.limit(6)//跟数据库中的limit有差不多
.forEach(System.out::println);//终止操作
}
skip(n):跳过元素,就是前n个元素不要,从第
n+1
个数开始,没有,就返回空
// (3)skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
@Test
public void testSkip() {
emps.stream()
.filter((e)->e.getAge()>8)
.skip(2)//这里可以查找filter过滤后的数据,前两个不要,要后面的,与limit相反
.forEach(System.out::println);//终止操作
}
distinct:就是去重,返回不重复的元素
原理:利用
hashCode()
和equals()
去除重复的元素,
// (4)distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
@Test
public void testDistinct() {
emps.stream()
.distinct()//去除重复的元素,因为通过流所生成元素的 hashCode() 和 equals() 去除重复元素,所以对象要重写hashCode跟equals方法
.forEach(System.out::println);//终止操作
}
2.Map
映射
- map()
- mapToDouble()
- mapToInt()
- mapToLong()
- flatMap()
map()
:就是接受一个函数作为参数,该参数会被应用到每个元素上,并且映射成一个新的元素
flatMap()
:接受一个函数作为参数,并且将流中每个值转换成另一个流,然后把所有的流连成一个流
直接复制了哈,这个代码感觉还是不错的,一起看看吧~哈哈
// map-接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
@Test
public void testMapAndflatMap() {
List<String> list=Arrays.asList("aaa","bbb","ccc","ddd");
list.stream()
.map((str)->str.toUpperCase())//里面是Function
.forEach(System.out::println);
System.out.println("----------------------------------");
//这里是只打印名字,map映射,根据Employee::getName返回一个name,映射成新的及结果name
emps.stream()
.map(Employee::getName)
.forEach(System.out::println);
System.out.println("======================================");
//流中流
Stream<Stream<Character>> stream = list.stream()
.map(StreamAPI::filterCharacter);
//{{a,a,a},{b,b,b}}
//map是一个个流(这个流中有元素)加入流中
stream.forEach(sm->{
sm.forEach(System.out::println);
});
System.out.println("=============引进flatMap=============");
// 只有一个流
Stream<Character> flatMap = list.stream()
.flatMap(StreamAPI::filterCharacter);
//flatMap是将一个个流中的元素加入流中
//{a,a,a,b,b,b}
flatMap.forEach(System.out::println);
}
/**
* 测试map跟flatMap的区别
* 有点跟集合中的add跟addAll方法类似 这个就好理解多了
* add是将无论是元素还是集合,整体加到其中一个集合中去[1,2,3.[2,3]]
* addAll是将无论是元素还是集合,都是将元素加到另一个集合中去。[1,2,3,2,3]
* @param str
* @return
*/
public static Stream<Character> filterCharacter(String str){
List<Character> list=new ArrayList<>();
for (Character character : str.toCharArray()) {
list.add(character);
}
return list.stream();
}
3.排序
自然排序:
sorted()
定制排序:
sorted(Comparator c)
: 就是里面写你想添加判断条件
货不多说,看测试代码
@Test
public void testSorted() {
List<String> list=Arrays.asList("ccc","aaa","bbb","ddd","eee");
list.stream()
.sorted()
.forEach(System.out::println);
System.out.println("=======定制排序=========");
//=====仔细瞅瞅这边
emps.stream()
.sorted((x, y) -> {
if(x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(), y.getAge());
}
}).forEach(System.out::println);
}
四.结束
1.查找与匹配
allMatch()
: 检查是否匹配所有元素
anyMatch()
: 检查是否至少匹配一个
元素
noneMatch()
: 是否没有匹配
的所有元素
findFirst()
: 返回第一个
元素
findAny()
: 返回当前流中的任意元素
count()
: 返回流中的元素总数
max(),min()
: 返回流中的最大最小值
forEach()
: 就是迭代循环
,贼常用的
**测试代码:**复制过来的,写的不好,可以留言哈!!!
//3. 终止操作
/*查找与匹配
allMatch——检查是否匹配所有元素
anyMatch——检查是否至少匹配一个元素
noneMatch——检查是否没有匹配的元素
findFirst——返回第一个元素
findAny——返回当前流中的任意元素
count——返回流中元素的总个数
max——返回流中最大值
min——返回流中最小值
*/
@Test
public void test() {
// emps.stream():获取串行流
// emps.parallelStream():获取并行流
System.out.println("==========allMatch==============");
boolean allMatch = emps.stream()
.allMatch((e)->e.getStatus().equals(Status.BUSY));
System.out.println(allMatch);
System.out.println("==========anyMatch==============");
boolean anyMatch = emps.stream()
.anyMatch((e)->e.getAge()>10);
System.out.println(anyMatch);
System.out.println("==========noneMatch==============");
boolean noneMatch = emps.stream()
.noneMatch((e)->e.getStatus().equals(Status.BUSY));
System.out.println(noneMatch);
System.out.println("==========findFirst==============");
Optional<Employee2> findFirst = emps.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))//按照工资排序并输出第一个
.findFirst();
System.out.println(findFirst);
System.out.println("==========findAny==============");
Optional<Employee2> findAny = emps.stream()
.filter((e)->e.getStatus().equals(Status.BUSY))
.findAny();
System.out.println(findAny);
System.out.println("==========count==============");
long count = emps.stream()
.count();
System.out.println(count);
System.out.println("==========max==============");
Optional<Double> max = emps.stream()
.map(Employee2::getSalary)
.max(Double::compare);
System.out.println(max);
System.out.println("==========min==============");
Optional<Employee2> min = emps.stream()
.min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(min);
}
2.归纳
reduce(T iden,BinaryOperator b)
:流中元素反复结合得到一个值,返回T
reduce(BinaryOperator b)
:流中元素反复结合得到一个值,返回Optional<T>
map-reduce
模式感兴趣可以骚操作一波
@Test
public void testReduce() {
List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream()
.reduce(0,(x,y)->x+y);
System.out.println(sum);
Optional<Double> reduce = emps.stream()
.map(Employee2::getSalary)
.reduce(Double::sum);
System.out.println(reduce.get());
}
3.收集
collect()
:你想收集成啥样的集合返回
Collectors
其中主要的方法:
方法名 作用 返回类型 toSet
把流中元素收集到set Set toList
将流中的元素收集到 List
List toCollection:
将流中的元素收集到自己创建的集合中 Collection counting
计算流中的元素个数 long summingInt
对元素中的整数类型求和 Integer averagingInt
求平均值 Double summarizingInt
收集流中Integer属性的统计值 IntSummaryStatistics
方法 作用 返回类型 joining
连接流中的每个字符串 String maxBy,minBy
根据比较器选择最大最小值 Optional reducing
归约 归约产生的类型 collectingAndThen
包裹另一个收集器并对其结果转换函数 转换函数返回的类型 groupingBy
根据某些属性值对流分组,属性为 k
,结果为v
Map<K,List> partitioningBy
根据true或false进行分区 Map<Boolean,List>
测试代码:
//===============
List<String> collect = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
//=====================================================
Set<String> collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toSet());
collect2.forEach(System.out::println);
//=======================================================
HashSet<String> collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toCollection(HashSet::new));
collect3.forEach(System.out::println);
//======================================================
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(collect.get());
Optional<Employee2> collect2 = emps.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect2.get());
//=======================================================
Optional<Double> collect4 = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println(collect4);
Optional<Employee2> collect3 = emps.stream()
.collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
System.out.println(collect3.get());
//====================================================
Double collect5 = emps.stream()
.collect(Collectors.summingDouble(Employee2::getSalary));
System.out.println(collect5);
//========================================================
Double collect6 = emps.stream()
.collect(Collectors.averagingDouble((e)->e.getSalary()));
Double collect7 = emps.stream()
.collect(Collectors.averagingDouble(Employee2::getSalary));
System.out.println("collect6:"+collect6);
System.out.println("collect7:"+collect7);
//=======================================================
//总数
Long collect8 = emps.stream()
.collect(Collectors.counting());
System.out.println(collect8);
//====================================================
DoubleSummaryStatistics collect9 = emps.stream()
.collect(Collectors.summarizingDouble(Employee2::getSalary));
long count = collect9.getCount();
double average = collect9.getAverage();
double max = collect9.getMax();
double min = collect9.getMin();
double sum = collect9.getSum();
System.out.println("count:"+count);
System.out.println("average:"+average);
System.out.println("max:"+max);
System.out.println("min:"+min);
System.out.println("sum:"+sum);
//=========================================================
//分组
@Test
public void testCollect3() {
Map<Status, List<Employee2>> collect = emps.stream()
.collect(Collectors.groupingBy((e)->e.getStatus()));
System.out.println(collect);
Map<Status, List<Employee2>> collect2 = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus));
System.out.println(collect2);
}
//=====多级==================================================
//多级分组
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
//===================================================
//多级分组
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
//==========================================================
//多级分组
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
//======================================================
//组接字符串
@Test
public void testCollect6() {
String collect = emps.stream()
.map((e)->e.getName())
.collect(Collectors.joining());
System.out.println(collect);
String collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(","));
System.out.println(collect3);
String collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(",", "prefix", "subfix"));
System.out.println(collect2);
}
@Test
public void testCollect7() {
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.reducing(Double::sum));
System.out.println(collect.get());
}
//==========================================================
总测试代码
/**
* collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
*/
@Test
public void testCollect() {
List<String> collect = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
Set<String> collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toSet());
collect2.forEach(System.out::println);
HashSet<String> collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toCollection(HashSet::new));
collect3.forEach(System.out::println);
}
@Test
public void testCollect2() {
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(collect.get());
Optional<Employee2> collect2 = emps.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect2.get());
Optional<Double> collect4 = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println(collect4);
Optional<Employee2> collect3 = emps.stream()
.collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
System.out.println(collect3.get());
System.out.println("=========================================");
Double collect5 = emps.stream()
.collect(Collectors.summingDouble(Employee2::getSalary));
System.out.println(collect5);
Double collect6 = emps.stream()
.collect(Collectors.averagingDouble((e)->e.getSalary()));
Double collect7 = emps.stream()
.collect(Collectors.averagingDouble(Employee2::getSalary));
System.out.println("collect6:"+collect6);
System.out.println("collect7:"+collect7);
//总数
Long collect8 = emps.stream()
.collect(Collectors.counting());
System.out.println(collect8);
DoubleSummaryStatistics collect9 = emps.stream()
.collect(Collectors.summarizingDouble(Employee2::getSalary));
long count = collect9.getCount();
double average = collect9.getAverage();
double max = collect9.getMax();
double min = collect9.getMin();
double sum = collect9.getSum();
System.out.println("count:"+count);
System.out.println("average:"+average);
System.out.println("max:"+max);
System.out.println("min:"+min);
System.out.println("sum:"+sum);
}
//分组
@Test
public void testCollect3() {
Map<Status, List<Employee2>> collect = emps.stream()
.collect(Collectors.groupingBy((e)->e.getStatus()));
System.out.println(collect);
Map<Status, List<Employee2>> collect2 = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus));
System.out.println(collect2);
}
//多级分组
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
//分区
@Test
public void testCollect5() {
Map<Boolean, List<Employee2>> collect = emps.stream()
.collect(Collectors.partitioningBy((e)->e.getSalary()>5000));
System.out.println(collect);
}
//组接字符串
@Test
public void testCollect6() {
String collect = emps.stream()
.map((e)->e.getName())
.collect(Collectors.joining());
System.out.println(collect);
String collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(","));
System.out.println(collect3);
String collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(",", "prefix", "subfix"));
System.out.println(collect2);
}
@Test
public void testCollect7() {
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.reducing(Double::sum));
System.out.println(collect.get());
}