Stream流知识总结

1、Strema概述

java 8 新增了Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。

什么是Stream流?

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

Stream可以由数组或集合创建,对流的操作分为两种:

  1. 中间操作,每次返回一个新的流,可以有多个。(筛选filter、映射map、排序sorted、去重组合skip—limit)
  2. 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。(遍历foreach、匹配find–match、规约reduce、聚合max–min–count、收集collect)

如下图所示,每个流可以进行多次中间操作,但是只能进行一次终端操作

在这里插入图片描述

2、Stream流和传统for循环遍历的对比

假设要输出所有姓张的三字名称,分别使用for循环和stream流来实现
for循环:

import java.util.ArrayList;
import java.util.List;
 
public class Demo1List {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("小昭");
        list.add("殷离");
        list.add("张三");
        list.add("张三丰");
 
        List<String> listA = new ArrayList<>();
        for ( String s  : list) {
            if (s.startsWith("张"))
                listA.add(s);
        }
 
        List<String> listB = new ArrayList<>();
        for (String s: listA) {
            if (s.length() == 3)
                listB.add(s);
        }
 
        for (String s: listB) {
            System.out.println(s);
        }
    }
}

stream流:

import java.util.ArrayList;
import java.util.List;
 
public class Demo2Steam {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("小昭");
        list.add("殷离");
        list.add("张三");
        list.add("张三丰");
        list.stream()
                .filter(name -> name.startsWith("张"))
                .filter(name -> name.length() == 3)
                .forEach(name -> System.out.println(name));
    }
}

差别显而易见,可以看出用Stream流写出的代码结构更清晰,代码意图更易于理解。

3、Stream流的创建

1、Cllection集合可以直接使用内置的stream()方法进行创建

List<String> list = Arrays.asList("a", "b", "c");
// 创建一个顺序流
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();
parallelStream.forEach(System.out::println);

2、数组可以使用Arrays.stream(T[] array)方法创建流

int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);

3、使用Stream的静态方法:of()、iterate()、generate()

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println);

Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);

4、stream和parallelStream的区别

stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作。使用并行流的前提是对流中的数据处理顺序没有要求。在流中数据量大的时候,并行流可以加快处理速度。

除了直接创建并行流,还可以通过parallel()方法把顺序流转换成并行流:

List<Integer> list = Arrays.asList(9, 11, 10, 8, 12, 4);
//将集合转换成顺序流
Stream<Integer> stream = list.stream();
//将顺序流转换成并行流
Stream<Integer> parallelstream = stream.parallel();
//打印
parallelstream.forEach(System.out::println);

打印结果为:8 4 12 9 11 10。

5、什么是Optional

在使用stream之前,先理解一个概念:Optional 。
在这里插入图片描述

Optional类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

6、Steam流的方法演示

(1)遍历流中元素:forEach
 List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
// 遍历流中的元素
list.stream().forEach(System.out::println);
//或者
list.stream().forEach(x -> System.out.println(x));

结果依次输出7, 6, 9, 3, 8, 2, 1

(2)匹配:findFirst、findAny、anyMatch、allMatch:
List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
// 匹配第一个
Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
// 匹配任意(适用于并行流)
Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
// 是否包含符合特定条件的元素
boolean anyMatch = list.stream().anyMatch(x -> x > 6);
//元素是否全部符合一定条件
boolean allMatch = list.stream().allMatch(x -> x > 6);
System.out.println("匹配第一个值:" + findFirst.get());
System.out.println("匹配任意一个值:" + findAny.get());
System.out.println("是否存在大于6的值:" + anyMatch);
System.out.println("是否存在大于6的值:" + allMatch);

输出结果为:
匹配第一个值:7
匹配任意一个值:8
是否存在大于6的值:true
是否存在大于6的值:false

(3)筛选:filter

筛选出大于6的值并打印输出:

List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
//筛选出大于6的值并打印输出
list.stream().filter(x -> x > 6).forEach(System.out::println);

输出结果:7, 6, 9,8

(4) max、min、count

max——获取Integer集合中的最大值:

public class StreamTest {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);

		// 自然排序
		Optional<Integer> max = list.stream().max(Integer::compareTo);
		// 自定义排序
		Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1.compareTo(o2);
			}
		});
		System.out.println("自然排序的最大值:" + max.get());
		System.out.println("自定义排序的最大值:" + max2.get());
	}
}

输出结果为:
自然排序的最大值:11
自定义排序的最大值:11

min与之相反。

count——计算Integer集合中大于6的元素的个数:

import java.util.Arrays;
import java.util.List;

public class StreamTest {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);

		long count = list.stream().filter(x -> x > 6).count();
		System.out.println("list中大于6的元素个数:" + count);
	}
}


结果输出:list中大于6的元素个数:4

(5)映射: map、flatMap

map
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
flatMap
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

映射,可以将一个流的元素按照一定的映射规则映射到另一个流中。分为map和flatMap:

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

map的应用(1)——将集合中的数全部+3:

List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);
//将每个数加3
List<Integer> newList = list.stream().map(x -> x+3).toList();`
System.out.println("每个元素+3:" + newList);

输出结果:每个元素+3:[10, 9, 12, 7, 14, 9]

map的应用(2)——将集合中的字母全部改为大写

String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).toList();
System.out.println("每个元素大写:" + strList);

输出结果:每个元素大写:[ABCD, BCDD, DEFDE, FTR]

flatMap的应用——将两个字符数组合并成一个新的字符数组

List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");
List<String> listNew = list.stream().flatMap(s -> {
        // 将每个元素转换成一个stream
        String[] split = s.split(",");
        Stream<String> s2 = Arrays.stream(split);
        return s2;
  }).toList();

System.out.println("处理前的集合:" + list);
System.out.println("处理后的集合:" + listNew);

输出结果:
处理前的集合:[m,k,l,a, 1,3,5,7]
处理后的集合:[m, k, l, a, 1, 3, 5, 7]

(6)归约:reduce

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

在这里插入图片描述
利用reduce()方法求Integer集合的元素之和,乘积,和最大值:

public class StreamTest {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
		// 求和方式1
		Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
		// 求和方式2
		Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
		// 求和方式3
		Integer sum3 = list.stream().reduce(0, Integer::sum);
		
		// 求乘积
		Optional<Integer> product = list.stream().reduce((x, y) -> x * y);

		// 求最大值方式1
		Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
		// 求最大值写法2
		Integer max2 = list.stream().reduce(1, Integer::max);

		System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);
		System.out.println("list求积:" + product.get());
		System.out.println("list求和:" + max.get() + "," + max2);
	}
}


输出:
list求和:29,29,29
list求积:2112
list求和:11,11

结语

以上是小编总结的Stream流的学习笔记,供交流学习使用,欢迎大家一起学习讨论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值