2.流的操作

接上篇文章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());
	}
}

九.流的组成

| _ _ _ _ _    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _   _ _ _ _ _|         | |                                | |         ||  Cart ----> filer  ---> sorted  ---> map ----->collect ||_ _ _ _ _| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| |_ _ _ _ _|||                      ||                      ||数据源                   中间操作                 终端操作

九.流操作分类

中间操作:数据执行完不销毁
终端操作:执行操作后数据销毁,一次性的

有状态:所有数据基础上
无状态:非所有数据基础上操作
非短路操作:所有基础上
短路操作:非所有数据基础上

中间操作(无状态)中间操作(有状态)终端操作(短路)终端操作(非短路)
过滤(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)


注:本文章是参考慕课网老师视频讲解总结,如有侵犯,请告知,可立即删除,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值