Java Stream流式操作白话文式解析,并举例

Stream

定义:流实际就是一批数据的集合,大大简化开发过程

方法解释

  1. filter 过滤操作:类似于if,将满足条件的数据保留下来
//给一个原数据,返回一个Boolean值
//满足布尔值的数据保留
Stream<T> filter(Predicate<? super T> predicate);
//Predicate可缩写为
A -> {
	//比较操作
	//例如:
	return A == B
}
  1. map 转换操作:将一个实体转换为另一个实体(A->B)
//接收一个转换方法。函数式接口之Function 
//返回值:属于实体B的Stream
<R> Stream<R> map(Function<? super T, ? extends R> mapper)  

//Function可缩写为
A -> {
	B result = new B();
	//转换逻辑
	return B
}
衍生转换家族:限定了转换结果,与map最明显的区别:仅仅能返回固定类型的实体
1. mapToInt: 限制转换结果为int
2. mapToLong:限制转换结果为 long
3. mapToDouble:限制转换结果为 double
存在的意义:可进行一些数学运算,比如sum,max,min等等。比如求出一批订单数据的招总金额
//其中有amount属性,金额
	List<Order> data = ......;
	//求出id最大的数据
	double totalAmount = data
						.stream()
						.mapToDoule(e -> return e.getAmount())
						//可简写为
						//.mapToDoublle(Order::getAmount)
						.sum();
  1. flatMap 集合转换操作(最难理解):将一个集合流平铺
//接收一个属于A的集合流
//返回一个属于A的流
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
//举例
//有一个被分组或者通过多线程读取到的一组订单数据
List<List<Order>> orderGroup = new ArrayList<>();
//现在要获取所有的数据
List<Order> totalOrder = orderGroup
						.stream()
						.flatMap(orders -> {
							return orders.stream;
						})
						//可简写为
						//.flatMap(List::stream)
						.collect(Collectors.toList());
衍生家族同上:
	1. flatMapToLong
	2. flatMapToDouble
	3. flatMapToInt
  1. distinct 去重:将流中重复数据去重,类似于MySQL的distinct
//去重规则为:A.equals(B)
//所以如果是对象流进行去重,一定要重写equals方法
Stream<T> distinct();

//有一组字符串数字数据,将其去重后求和
List<String> numbers = new ArrayList<>();
int total = numbers
			.stream()
			//过滤掉为空串的
			.filter(e -> e != null && e != "")
			//转化为int流
			.mapToInt(Integer::valueOf)
			.distinct()
			.sum();
  1. sorted 排序:将流中的数据进行一定规则的排序
//比较器 必须为Comparator的子类,可使用lamda表达式
//可理解为 Collections.sorted();
Stream<T> sorted(Comparator<? super T> comparator)

//将订单集合按照各个订单的金额大小排序
List<Order> orders = new ArrayList<>();
List<Order> result = orders
.stream()
.sorted(order -> Comparator.comparingDouble(Order::getAmount).reversed())
.collect(Collectors.toList());
  1. peek 处理:将流中的数据进行处理,不进行转换
//与map的区别:
//map是将一个实体转换为另一个实体:A->B
//peek仅对原数据处理,对实体类型没有影响。
//如果不需要流处理结果,也就是规约操作,相当于foreach
//所以一般用于流过程调试或实体转换后赋值
Stream<T> peek(Consumer<? super T> action);

//举例
//有一个被分组或者通过多线程读取到的一组订单数据
List<List<Order>> orderGroup = new ArrayList<>();
//现在我需要获取所有的订单数据,我需要得到订单当前确切的结果
List<Order> result = orderGroup
					.stream()
					.flatMap(List::stream)
					.peek(order -> {
						order.setStatus("已支付");
					})
					.collect(Collector.toList());
  1. limit 限制集合个数:类似于MySQL的分页limit,返回指定个数的数据
Stream<T> limit(long maxSize);

//将order按金额大小排序,并返回金额最高的十单
List<Order> result = orders
	.stream()
	.sorted(e -> Comparator.compareDouble(Order::getAmount).reversed())
	.limit(10)
	.collect(Collectors.toList());
  1. skip 跳过:跳过指定个数的元素,类似于MySQL的分页第一个参数
Stream<T> skip(long n);

//获取order订单列表的第二页数据,每页数据为10条
int currentPage = 2,size = 10;
List<Order> result = orders
					.stream()
					.skip((currentPage - 1) * size)
					.limit(size)
					.collect(Collector.toList());
  1. forEach 遍历:类似于集合的foreach,基本不用
  2. forEachOrdered 顺序遍历:按照集合原本定义数据遍历,一般用于并行流中
void forEachOrdered(Consumer<? super T> action);

① 在并行流中forEach不保证按顺序执行。

Stream.of("A","B","C", "D")
 .parallel()
 .forEach(e -> System.out.println(e)); 
输出可能是C B A D,输出不一定是按顺序执行。

② forEachOrdered方法总是保证按顺序执行。

Stream.of("A","B","C", "D")
 .parallel()
 .forEachOrdered(e -> System.out.println(e)); 
输出为A B C D
  1. toArray 终端规约操作:将流转为数组
<A> A[] toArray(IntFunction<A[]> generator);

//将order转为orderVo数组
OrderVo[] result = orders
			.stream()
			.map(order -> return transferVo(order))
			.toArray(OrderVo[]::new);
  1. reduce 规约:使用累积函数对元素进行处理,最后返回一个值
//给予一个初始值,在该值基础上进行累计函数
T reduce(T identity, BinaryOperator<T> accumulator);
//不给予初始值,进行累积,与上述的区别在于返回值。因为如果没有初始值并且
//流中没有元素,那么就会返回空。
Optional<T> reduce(BinaryOperator<T> accumulator);
//使用reduce实现求和
List<Integer> numbers = Arrays.asList(1,2,3,4,5);
int sum = numbers
			.stream()
			.reduce(0L,(a,b) -> a + b);

//给予另一个类型的初始值,进行累积
//与上述的区别是,初始值的类型可以与流类型不同,类似于map+reduce的功能
//用的不多
<U> U reduce(U identity,  
             BiFunction<U, ? super T, U> accumulator,  
             BinaryOperator<U> combiner);
//对一个数字集合累乘,最后结果可能大于int的取值范围,所以需要转为long          
List<Integer> numbers = Arrays.asList(9999,8888,7777,6666,5555);  
Long reduce = numbers  
        .stream()  
        .reduce(1L, (a, b) -> a * b, (a, b) -> 1L);
  1. min 最小值:根据比较器获取流中最小的元素
  2. max 最大值:根据比较器获取流中最大的元素
  3. count 计数:获取流中有多少个元素
  4. anyMatch 任意匹配:根据比较规则,流中元素如果有任意一个符合就返回true
//与filter的区别为
//filter:过滤掉不符合条件的数据
//match:判断流中是否存在符合条件的元素
boolean anyMatch(Predicate<? super T> predicate);
  1. allMatch 全部匹配 :流中元素是否全部符合条件
  2. noneMatch 是否没有元素匹配条件:allMatch反过来
  3. findFirst 返回流中的第一个元素

//一般只需获取某种满足条件的第一条元素
Optional<T> findFirst();

//获取张三最近的第一条订单
List<Order> orders = new ArrayList<>();
Optional<Order> result = orders
		.stream()
		.sorted(e -> Compartor.compare(Order::getPayTime).reversed())
		.findFirst();
  1. findAny 返回流中任意一个元素
  2. collect 收集: 一般用Collectors静态方法
    1. toCollection:收集为指定的集合
    2. toList:toCollection的具体化,收集为List集合
    3. toSet:toCollection的具体化,收集为Set集合
    4. joining:类似于String.join方法
    public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,  
                                                         CharSequence prefix,  
                                                         CharSequence suffix)
    //获取订单付款人并以逗号分隔
    String  payUsers = orders
    		.stream()
    		.map(Order::getPayUserName)
    		.joining(",")
    
    1. groupBy 根据指定规则分组
    //根据订单付款人分组
    Map<String,List<Order>> result = orders
    	.stream()
    	.collect(Collectors.groupBy(Order::getPayUserId));
    
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值