Java:StreamAPI

1 概述

Java8中有两大最为重要的改变。第一个是Lambda 表达式;另外一个则是Stream API。

Stream API ( java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream 是Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL 执行的数据库查询。也可以使用Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

就是用来处理集合、数组的API,集合讲的是数据,而流是计算。

注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

2 运行机制

Stream分为源source , 中间操作,终止操作。

  • 创建Stream
    一个数据源(如:集合、数组),获取一个流
  • 中间操作
    一个中间操作链,对数据源的数据进行处理
    一个流可以有0~N个中间操作,每一个中间操作都会返回一个新的流,方便下一个操作使用
    一个流只能有一个终止操作
    中间操作也称为转换算子-transformation
  • 终止操作(终端操作)
    一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
    Stream只有遇到终止操作,它对策数据源才会开始执行遍历等操作
    终止操作也称为动作算子
    因为动作算子的返回值不再是Stream,所以这个计算就终止
    只有碰到动作算子的时候,才会真正的计算

3 创建Stream

(1)通过数组 Stream.of(数组对象);

(2)通过集合 集合对象.stream();

(3)通过Stream.generate(); 方法来创建

  • 通过这种方式创建的流,无限大,在操作的时候,最好使用limit进行最大数量限制
  • generate的参数是 Supplier,只有一个get方法,是无参有返回值的
  • get方法的返回值,作为整个集合中的数据

(4)通过Stream.iterate();方法来创建

  • 这是一个无限流,无限大,通过这种方式创建的流,在操作的时候,最好使用limit进行最大数量限制
  • 比如:Stream.iterate(1, x->x+2);
    第一个参数是起始值,第二个参数是UnaryOperator 继承了Function 所以有参有返回值,1 就是起始值, x+2 就是步长,类似于一个死循环,起始值是1,步长是2,终止条件是true

(5)已有类的Stream源生成API

  • 比如:String str = “abc”;
    IntStream chars = str.chars();
public static void main(String[] args) {
    
    

	// 1 通过数组 Stream.of(数组对象)
	String[] strings = {
    
     "a", "b", "c", "d" };
	Stream<String> stream1 = Stream.of(strings);

	// 2 通过集合
	List<String> strings2 = Arrays.asList(strings);
	Stream<String> stream2 = strings2.stream();

	// 3 通过Stream.generate 方法来创建
	Stream<Integer> generate = Stream.generate(() -> 1);
	// 通过limit限制最多元素个数
	generate.limit(5).forEach(x -> System.out.println(x));
	
	// 4 通过Stream.iterate 方法来创建
	Stream<Integer> iterate = Stream.iterate(1, x->x+2);
	iterate.limit(5).forEach(x->System.out.println(x));
	
	// 5 已有类的Stream源生成API
	String str = "abc";
	IntStream chars = str.chars();
	chars.forEach(x->System.out.println(x));
}

4 常用的转换算子

  • filter : 对元素进行过滤,不符合条件的,就舍弃
  • distinct : 去重
  • skip : 跳过多少个元素
  • limit : 取一个集合中的前几条数据
  • map : 可以理解为是在遍历集合的过程中,对元素进行操作,比如进行判断,集合元素是否大于4 ,返回值为boolean类型,或者对集合元素进行更改,比如每个元素都自身+1
  • flatMap : 解决一个字符串数组,返回单一的字符串使用flatMap

注意 只有这些算子是不会真正进行计算的,只有调用动作算子,才会真正计算。

public static void main(String[] args) {
    
    
	String[] arr = {
    
     "a", "b", "c", "a" };//创建字符串数组
	List<String> strings = Arrays.asList(arr);//数组转为集合
	// 利用集合创建流
	Stream<String> stream = strings.stream();
	/**
	 * filter : 对元素进行过滤,不符合条件的,就舍弃
	 * 
	 * collect : 动作算子,把符合条件元素的转换为集合
	 */
	// 只要a
	List<String> value = stream.filter(x -> x.equals("a")).collect(Collectors.toList());
	System.out.println(value);//[a, a]
	
	// 注意:stream在使用后 必须重新生成

	// 利用集合重新创建流
	stream = strings.stream();
	/**
	 * skip : 跳过n个元素,比如原来是abca 跳过1个 就是bca
	 */
	value = stream.skip(1).collect(Collectors.toList());
	System.out.println(value);//[b, c, a]

	// 重新生成流
	stream = strings.stream();
	// 如果元素是a就返回true,否则就返回false,把返回结果形成一个新的集合
	List<Boolean> value1 = stream.map(x -> x.equals("a")).collect(Collectors.toList());
	System.out.println(value1);//[true, false, false, true]
	
	// 重新生成流
	stream = strings.stream();
	// 更改集合元素
	value = stream.map(x -> x + "---").collect(Collectors.toList());
	System.out.println(value);//[a---, b---, c---, a---]

	// 重新生成流
	stream = strings.stream();
	value = stream.distinct().collect(Collectors.toList());
	System.out.println(value);// [a, b, c]

	// 重新生成流
	stream = strings.stream();
	//limit():取前几条数据
	value = stream.limit(2).collect(Collectors.toList());
	System.out.println(value);// [a, b]

	String[] arr1 = {
    
    "1,2,3","a,b,c"};
	strings = Arrays.asList(arr1);
	// 现在集合中有两个数据,分别是 "1,2,3"  和 "a,b,c"
	// 把数组中每一个元素都拿出来,分别以 , 逗号分割,形成两个字符串数组
	// 最终通过 collect 合并到一起, 得到 1,2,3,a,b,c 6个元素
	stream = strings.stream();//生成流
	value = stream.map(x->x.split(",")).flatMap(array->Arrays.stream(array)).collect(Collectors.toList());
	System.out.println(value);// [1, 2, 3, a, b, c]
}

5 常用的动作算子

  • forEach : 循环
  • 计算 : min,max,count,average
  • 匹配 : anyMatch,allMatch,noneMatch,findFirst,findAny
  • 汇聚 : reduce
  • 收集器 : collect
public static void main(String[] args) {
    
    
	String[] arr = {
    
    "a","b","c"}; //创建集合
	List<String> strings = Arrays.asList(arr);//转换为数组
	Stream<String> stream = strings.stream();//生成流
	
	// 测试forEach
	// 先只要 a ,然后输出
	stream.filter(x->x.equals("a")).forEach(x->System.out.println(x));
	
	// 测试 count
	//重新生成流
	stream= strings.stream();
	// 获取多少个数据
	// 如果只想获取条数,可以调用集合的 size方法,更简单
	// 只是有动作算子价值不大,一般和转换算子一起使用,才能体现优势
	long count = stream.count();
	System.out.println(count);//3
	
	// collect:收集器
	// 把结果组织成集合
	stream= strings.stream();//重新生成流
	// 修改元素
	List<String> list = stream.map(x->x+"==").collect(Collectors.toList());
	System.out.println(list);// [a==, b==, c==]
}

猜你喜欢

转载自blog.csdn.net/qq_41504815/article/details/113575927