接上篇文章1.Lambda介绍及使用
七.流的简介(非IO流)
【1】JDK1.8引入的新成员,以声明式方式处理集合数据
【2】将基础操作连接起来,完成复杂的数据处理流水线
【3】提供透明的并行处理
八.流与集合的区别
【1】时间与空间
集合面向存储,流面向计算
【2】只能遍历一次
【3】外部迭代与内部迭代
package com.xyking.stream;
import com.alibaba.fastjson.JSON;
import com.xyking.lambda.cart.CartService;
import com.xyking.lambda.cart.Sku;
import com.xyking.lambda.cart.SkuCategoryEnum;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* 对比: 原始集合操作与Stream集合操作
*/
public class StreamVs {
/**
* 1.想看看购物车都有什么商品
* 2. 图书类商品都给买
* 3.其余的商品中买两件最贵的
* 4.只需要两件商品的名称和总价
*/
/**
* 以原始集合操作实现需求
*/
@Test
public void oldCartHandle() {
// 1.打印所有商品
List<Sku> cartSkuList = CartService.getCartSkuList();
for (Sku sku :
cartSkuList) {
System.out.println(JSON.toJSONString(sku, true));
}
// 2.图书类过滤掉
List<Sku> notBooksSkuList = new ArrayList<>();
for (Sku sku : cartSkuList
) {
if (!SkuCategoryEnum.BOOKS.name().equals(sku.getSkuName())) {
notBooksSkuList.add(sku);
}
}
// 排序
notBooksSkuList.sort(new Comparator<Sku>() {
@Override
public int compare(Sku o1, Sku o2) {
if (o1.getTotalPrice() > o2.getTotalPrice()) {
return -1;
} else if (o1.getTotalPrice() < o2.getTotalPrice()) {
return 1;
}
return 0;
}
});
List<Sku> top2SkuList = new ArrayList<>();
for (int i = 0; i < 2; i++) {
top2SkuList.add(notBooksSkuList.get(i));
}
// 4.求两件商品的总价
Double money = 0.0;
for (Sku sku : top2SkuList) {
money += sku.getTotalPrice();
}
/**
* 获取两商品的名称
*/
List<String> resultSkuNameList = new ArrayList<>();
for (Sku sku : top2SkuList) {
resultSkuNameList.add(sku.getSkuName());
}
// 打印输出结果
System.out.println(JSON.toJSONString(resultSkuNameList, true));
System.out.println("商品总价:" + money);
}
/**
* 以Stream流方式实现操作
*/
@Test
public void newCartHandle() {
AtomicReference<Double> money =
new AtomicReference<>(Double.valueOf(0.0));
List<String> resultSkuNameList = CartService.getCartSkuList()
.stream()
/**
* 打印商品信息
*/
.peek(sku -> System.out.println(JSON.toJSONString(sku, true)))
/**
* 2.过滤掉所有图书类商品
*/
.filter(sku -> !SkuCategoryEnum.BOOKS.name().equals(sku.getSkuCategory()))
/**
* 排序
*/
.sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
/**
* Top2
*/
.limit(2)
/**
* 计算总价格
*/
.peek(sku -> money.set(money.get() + sku.getTotalPrice()))
/**
* 获取商品名称
*/
.map(sku -> sku.getSkuName())
.collect(Collectors.toList());
// 打印输出结果
System.out.println(JSON.toJSONString(resultSkuNameList, true));
System.out.println("商品总价:" + money.get());
}
}
九.流的组成
九.流操作分类
中间操作:数据执行完不销毁
终端操作:执行操作后数据销毁,一次性的
有状态:所有数据基础上
无状态:非所有数据基础上操作
非短路操作:所有基础上
短路操作:非所有数据基础上
中间操作(无状态) | 中间操作(有状态) | 终端操作(短路) | 终端操作(非短路) |
---|---|---|---|
过滤(filter) | 排序(sorted) | 所有匹配(allMatch) | 遍历(forEach) |
映射(map) | 去重(distinct) | 任意匹配(anyMatch) | 规约(reduce) |
遍历(peek) | 跳过(skip) | 不匹配(noneMatch) | 最大值(max) |
扁平化(flatMap) | 截断(limit) | 查找首个(findFirst) | 聚合(collect) |
查找任意(findAny) | 最小值(min) | ||
计数(count) |
package com.xyking.stream;
import com.alibaba.fastjson.JSON;
import com.xyking.lambda.cart.CartService;
import com.xyking.lambda.cart.Sku;
import com.xyking.lambda.cart.SkuCategoryEnum;
import org.junit.Before;
import org.junit.Test;
import java.util.*;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;
/**
* 演示流的各种方法
*/
public class StreamOperator {
List<Sku> list;
@Before
public void init() {
list = CartService.getCartSkuList();
}
//========================中间操作(无状态:无需经过全部数据)================================
//过滤(filter): 过滤掉不符合断言判断的数据(过滤掉不符合条件的数据)
//映射(map):将一个元素转换成另外一个元素对象(如将Sku对象转化为skuName对象)
//扁平化(flatMap):将一个对象转换成一个流
//遍历(peek):对流中元素进行遍历操作(不会对流进行销毁,后续可继续使用)
/**
* filter使用: 过滤掉不符合断言判断的数据(Predicate函数式接口,用于判断)
*
*/
@Test
public void filterTest() {
list.stream()
// filter
.filter(sku ->
SkuCategoryEnum.BOOKS.name()
.equals(sku.getSkuCategory().name()))
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
/**
* map使用:将一个元素转换成另外一个元素(Function<T,R>函数式接口 转换一个对象为不同类型的对象)
*/
@Test
public void mapTest() {
list.stream()
// map
.map(sku -> sku.getSkuName())
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
/**
* flatMap使用:将一个对象转换成一个流
*/
@Test
public void flatMapTest() {
list.stream()
.flatMap(sku -> Arrays.stream(sku.getSkuName().split("")))
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
/**
* peek使用: 对流中元素进行遍历操作(不会对流进行销毁,后续可继续使用)
*/
@Test
public void peek() {
list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
//=====================================中间操作(有状态:必须重新操作全部数据)===================================
//去重(distinct):对流元素进行去重,有状态操作
//跳过(skip) : 跳过跳过前n条数据
//截断(limit): 截断获取前n条数据 可与skip进行简单分页操作
//排序(sorted) : 对流中元素进行排序,可选择自然排序或者指定排序规则
/**
* sorted使用: 对流中元素进行排序,可选择自然排序或者指定排序规则,有状态操作
*/
@Test
public void sortTest() {
list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.sorted(Comparator.comparing(Sku::getTotalPrice))
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
/**
* distinct使用: 对流元素进行去重,有状态操作
*/
@Test
public void distinctTest() {
list.stream()
.map(sku -> sku.getSkuCategory())
.distinct()
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
/**
* skip使用: 跳过跳过前n条数据
*/
@Test
public void skipTest() {
list.stream()
.sorted(Comparator.comparing(Sku::getTotalPrice))
.skip(3)
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
/**
* limit使用:截断获取前n条数据
* 可以与skip简单操作分页
*/
@Test
public void limitTest() {
list.stream()
.sorted(Comparator.comparing(Sku::getTotalPrice))
.skip(3*2)
.limit(3)
.forEach(item ->
System.out.println(JSON.toJSONString(item, true)));
}
//===============================终端操作,用完直接销毁(短路) =================================
//所有匹配(allMatch):终端操作,短路操作 判断所有流元素满足条件返回true
//任意匹配(anyMatch):判断所有流元素中任意一个元素满足条件返回true
//不匹配(noneMatch) :判断所有流元素都不满足条件返回true
//查找首个(findFirst) :找到第一个元素
//查找任意(findAny) :找到任何一个元素,并行上速度更快,串行上与findFirst基本没有区别
/**
* allMatch使用: 终端操作(依次消费满足条件元素),短路操作(遇到不满足就不往后执行) 判断所有流元素满足条件返回true
*/
@Test
public void allMatchTest() {
boolean b = list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.allMatch(sku -> sku.getTotalPrice() > 100);
System.out.println(b);
}
/**
* anyMatch使用: 判断所有流元素中任意一个元素满足条件返回true
*/
@Test
public void anyMatchTest() {
boolean b = list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.anyMatch(sku -> sku.getTotalPrice() > 100);
System.out.println(b);
}
/**
* noneMatch使用: 判断所有流元素都不满足条件返回true
*/
@Test
public void noneMatchTest() {
boolean b = list.stream()
.peek(sku -> System.out.println(sku.getSkuName()))
.noneMatch(sku -> sku.getTotalPrice() < 20);
System.out.println(b);
}
/**
* findFirst使用: 找到第一个元素
*/
@Test
public void findFirstTest() {
Optional<Sku> optionalSku = list.stream()
.findFirst();
System.out.println(JSON.toJSONString(optionalSku.get(), true));
}
/**
* findAny使用: 找到任何一个元素,并行上速度更快,串行上与findFirst基本没有区别
*/
@Test
public void findAnyTest() {
Optional<Sku> optionalSku = list.stream()
.findAny();
System.out.println(JSON.toJSONString(optionalSku.get(), true));
}
//=============================== 终端操作(非短路)=====================================
//遍历(forEach)
//规约(reduce)
// 最大值(max) :获取元素最大值
//聚合(collect)
//最小值(min):获取元素最小值
//计数(count):获取流总个数
/**
* max使用: 获取元素最大值
*
*/
@Test
public void maxTest() {
OptionalDouble max = list.stream()
.mapToDouble(Sku::getTotalPrice)
.max();
System.out.println(max.getAsDouble());
}
/**
* min使用: 获取元素最小值
*
*/
@Test
public void minTest() {
OptionalDouble min = list.stream()
.mapToDouble(Sku::getTotalPrice)
.min();
System.out.println(min.getAsDouble());
}
/**
* count使用: 获取流总个数
*
*/
@Test
public void countTest() {
long count = list.stream()
.count();
System.out.println(count);
}
}
十.流的构建
①.由值创建流
②.由数组创建流
③.由文件生成流
④.由函数生成流(无限流)
package com.xyking.stream;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* 流的四种构建形式
*/
public class StreamConstructor {
/**
* ①.由值创建流
*/
@Test
public void streamFromValue() {
Stream<String> stream = Stream.of("小明", "小智", "小德", "小轩", "小泽");
stream.forEach(System.out::println);
}
/**
* ②.由数组创建流
*/
@Test
public void streamFromArray() {
int[] numbers = {5, 2, 0, 1, 3, 1, 4};
IntStream stream = Arrays.stream(numbers);
stream.forEach(System.out::println);
}
/**
* ③.由文件生成流
* @throws IOException .
*/
@Test
public void streamFromFile() throws IOException {
Stream<String> stream = Files.lines(Paths.get("D:\\workspace\\ideaworkspace\\yking\\src\\test\\java\\com\\xyking\\stream\\StreamConstructor.java"));
stream.forEach(System.out::println);
}
/**
* ④.由函数生成流(无限流)
*/
@Test
public void streamFromFunction() {
// 1
// Stream<Integer> stream = Stream.iterate(0, n -> n + 2);
// 2
Stream<Double> stream = Stream.generate(Math::random);
stream
.limit(100)
.forEach(System.out::println);
}
}
十一.收集器简介
1.将流中的元素累积成一个结果
2.作用于终端操作collect()上
3.collect / Collector / Collectors
十二.预定义收集器功能
1.将流元素归约和汇总为一个值
2.将流元素分组
3.将流元素分区
package com.xyking.stream;
import com.alibaba.fastjson.JSON;
import com.xyking.lambda.cart.CartService;
import com.xyking.lambda.cart.Sku;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 常见预定义收集器使用
*/
public class StreamCollector {
/**
* 1.将流元素归约和汇总为一个值
*/
@Test
public void toList() {
List<Sku> list = CartService.getCartSkuList();
List<Sku> collect = list.stream()
.filter(sku -> sku.getTotalPrice() > 100)
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(collect, true));
}
/**
* 2.将流元素分组
*/
@Test
public void group() {
List<Sku> list = CartService.getCartSkuList();
Map<Object, List<Sku>> collect = list.stream()
.collect(Collectors.groupingBy(sku -> sku.getSkuCategory()));
System.out.println(JSON.toJSONString(collect, true));
}
/**
* 3.将流元素分区
*/
@Test
public void partition() {
List<Sku> list = CartService.getCartSkuList();
Map<Boolean, List<Sku>> collect = list.stream()
.collect(Collectors.partitioningBy(sku -> sku.getTotalPrice() > 100));
System.out.println(JSON.toJSONString(collect, true));
}
}
//更多收集器需要自己去实践
其他:
1.maven引用
<!--json打印-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
//2.类对象集合,自己创建去实践
List<Sku> list = CartService.getCartSkuList();
前两篇文章总结:
`一.Lambda 表达式简介`
1.Java8 引入函数式编程风格
2.可以理解为一种匿名函数的替代
3.通过行为参数化传递代码
`二.Lambda 表达式的形式`
1.(parameters) -> expression
2.(parameters) -> {statement;}
①形式一: 没有参数
() -> System.out.println("Hello World!!!");
②形式二: 只有一个参数
name -> System.out.println("Hello World from" + name + "!!!");
③形式三: 没有参数,逻辑复杂
() -> {
System.out.println("Hello");
System.out.println("World");
}
④形式四: 包含两个参数的方法
简:
(x, y) -> x + y;
繁(具体逻辑):
BinaryOperator<Long> functionAdd = (x, y) -> x + y;
Long result = functionAdd.apply(1L, 2L);
⑤形式五: 对参数显示声明
简:
(Long x, Long y) -> x + y;
繁(具体逻辑):
BinaryOperator<Long> functionAdd = (Long x, Long y) -> x + y;
Long result = functionAdd.apply(1L, 2L);
`三.函数式接口`
1. 接口只有一个抽象方法
2. Java8的函数式接口注解:@FunctionInterface
3. 函数式接口的抽象方法签名:函数描述符
`四.自定义函数式接口`
详细内容请参考
1.yking\src\main\java\com\xyking\lambda\file 文件夹下内容
2.yking\src\main\java\com\xyking\lambda\cart 文件夹下内容
`五.常用函数接口及使用`
具体参考jdk8中对应的函数接口定义
jdk1.8.0_171\jre\lib\rt.jar!\java\util\function
`六.方法引用`
介绍:
调用特定方法的Lambda表达式的一种快捷写法,
可以让你重复使用现有的方法定义,
并像Lambda表达式一样传递他们
形式:
Sku(目标引用) ::(双冒号分隔符) getSkuPrice(方法名)
即 Sku :: getSkuPrice
具体参考lambda包下MethodYY类
* 常见函数式接口
* Predicate<T> 用于判断对象,比如求一个人是否是男性</>
* Consumer<T> 用于接收一个对象进行处理但没有返回,比如接收一个人并打印他的名字</>
* Function<T,R> 转换一个对象为不同类型的对象</>
* Supplier<T> 提供一个对象</>
* UnaryOperator<T> 接收对象并返回同类型对象</>
* BinaryOperator<T> 接收两个同类型对象,并返回原类型对象</>
`七.流的简介(非IO流)`
【1】JDK1.8引入的新成员,以声明式方式处理集合数据
【2】将基础操作连接起来,完成复杂的数据处理流水线
【3】提供透明的并行处理
` 八.流与集合的区别`
【1】时间与空间
集合面向存储,流面向计算
【2】只能遍历一次
【3】外部迭代与内部迭代
`九.流的组成`
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| | | | | |
| Cart ----> filer ---> sorted ---> map ----->collect |
|_ _ _ _ _| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| |_ _ _ _ _|
|| || ||
数据源 中间操作 终端操作
`九.流操作分类`
中间操作:数据执行完不销毁
终端操作:执行操作后数据销毁,一次性的
有状态:所有数据基础上
无状态:非所有数据基础上操作
非短路操作:所有基础上
短路操作:非所有数据基础上
中间操作(无状态) 中间操作(有状态) 终端操作(短路) 终端操作(非短路)
过滤(filter) 去重(distinct) 所有匹配(allMatch) 遍历(forEach)
映射(map) 跳过(skip) 任意匹配(anyMatch) 规约(reduce)
扁平化(flatMap) 截断(limit) 不匹配(noneMatch) 最大值(max)
遍历(peek) 排序(sorted) 查找首个(findFirst) 聚合(collect)
查找任意(findAny) 最小值(min)
计数(count)
`十.流的构建`
①.由值创建流
②.由数组创建流
③.由文件生成流
④.由函数生成流(无限流)
`十一.收集器简介`
1.将流中的元素累积成一个结果
2.作用于终端操作collect()上
3.collect / Collector / Collectors
`十二.预定义收集器功能`
1.将流元素归约和汇总为一个值
2.将流元素分组
3.将流元素分区
`十三.规约与汇总`
1.规约(reduce): 将Stream流中元素转换成一个值
2.汇总(collect) : 将Stream流中元素转换成一个容器(Map,List,Set)
注:本文章是参考慕课网老师视频讲解总结,如有侵犯,请告知,可立即删除,谢谢