流式编程 stream

目录

流式编程 stream

 Stream 的另外一大特点 

使用Stream步骤

创建stream

创建方法1:可以使用Arrays.stream()方法来使用Stream

创建方法2:Stream stream = list.parallelStream();

创建方法3:Collection.stream()用Java集合都创建一个Stream

Stream接口创建无限Stream的静态方法

遍历操作

流的转换


流式编程 stream

Stream中文称为流,通过将集合转换为这么一种叫做流的元素序列,通过声明性方式,能够对集合中的每个元素进行一系列并行或串行的流水线操作

Java 8中的Stream是对集合Collection对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作或者大批量数据操作

Stream API借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用Stream API无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物

Stream不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如过滤掉长度大于10的字符串、获取每个字符串的首字母等,Stream会隐式地在内部进行遍历,做出相应的数据转换。Stream就如同一个迭代器Iterator,单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。

 而和迭代器又不同的是,Stream可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个item读完后再读下一个item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream的并行操作依赖于Java7中引入的Fork/Join框架(JSR166y)来拆分任务和加速处理过程。

 Stream 的另外一大特点 

数据源本身可以是无限的

当使用一个流的时候,通常包括三个基本步骤:获取一个数据源source → 数据转换 → 执行操作获取想要的结果。每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道

Integer transactionsIds = 
		roomList.stream()  //将List转换为stream对象
 			.filter(b -> b.getLength() == 10) //针对stream种的数据元素进行过滤,只使用为true
 		    .sorted((x,y) -> x.getHigh() - y.getHigh()) //针对stream种的数据进行自定义规则的排序
 			.mapToInt(Room::getWidth)	//从集合元素通过调用当前对象getWidth方法获取对应的int类型数据
 			.sum();  //针对整数值进行求和处理

使用Stream步骤

1. 创建Stream;
2. 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换)
3. 对Stream进行聚合(Reduce)操作,获取想要的结果;

创建stream

流可以是顺序的也可以是并行的。顺序流的操作是在单线程上执行的,而并行流的操作是在多线程上并发执行的

创建方法1:可以使用Arrays.stream()方法来使用Stream

Integer[] array = new Integer[]{3,4,8,16,19,27,23,99,76,232,33,96};
long count = Arrays.stream(array).filter(i->i>20).count();

Collection.parallelStream使用并行流提高性能,处理任务时并行处理,前提是硬件支持,如果单核CPU,只会存在并发处理而不会并行
ParallelStream在使用上与Stream无区别,本质返回的都是一个流,只不过底层处理时根据条件判断是并行或者是串行
并行流并不会按照原本的顺序轨迹执行,而是随机执行,当然对于forEach输出也可以做到顺序串行,

 List<Integer> list = ...;
 // 使用List创建一个并行流对象Stream

创建方法2:Stream<Integer> stream = list.parallelStream();

Stream<Integer> stream = list.stream();

创建方法3:Collection.stream()用Java集合都创建一个Stream

特殊类型的Stream实现

IntStream、LongStream和DoubleStream

官方建议使用对应类型的Stream?
当然也可以用`Stream<Integer>`、`Stream<Long>`和`Stream<Double>`,但是boxing/unboxing
会很耗时,所以特别为这三种基本数值型提供了对应的Stream

IntStream.of(new int[]{1,2,3}).forEach(System.out::println);
IntStream.range(1,10).forEach(System.out::println);
IntStream.rangeClosed(1,3).forEach(System.out::println)

针对BufferedReader可以生成stream实现一行一行数据的读取

 ufferedReader br = new BufferedReader(new FileReader("d:/aaa.txt"));
        Stream<String> stream = br.lines();

Stream接口创建无限Stream的静态方法

generate()方法接受一个参数函数用来创建无限Stream的静态方法

Stream<String> stream = Stream.generate(() -> "test").limit(10);
String[] strArr = stream.toArray(String[]::new);
System.out.println(Arrays.toString(strArr));

iterate()方法接受一个参数函数用来创建无限Stream

Stream<BigInteger> bigIntStream = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.TEN)).limit(10);
BigInteger[] bigIntArr = bigIntStream.toArray(BigInteger[]::new);
System.out.println(Arrays.toString(bigIntArr));

遍历操作

Stream提供了方法forEach来迭代流中的每个数据

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

forEach方法接收一个Lambda表达式,然后在Stream的每一个元素上执行该表达式。不能修改自己包含的本地变量值,也不能用break/return之类的关键字提前结束循环

numbers.stream().forEach(number->{ System.out.println(number); });

流的转换

操作符就是对数据进行的一种处理工作,一道加工程序;就好像工厂的工人对流水线上的产品进行一道加工程序一样。
Stream的操作符大体上分为两种:中间操作符和终止操作符

- 对于数据流来说,中间操作符在执行制定处理程序后,数据流依然可以传递给下一级的操作符
- map(mapToInt,mapToLong,mapToDouble) 转换操作符,把比如A->B,这里默认提供了转int,long,double的操作符
- flatmap(flatmapToInt,flatmapToLong,flatmapToDouble) 拍平操作,比如把 int[]{2,3,4} 拍平变成 2,3,4 也就是从原来的一个数据变成了3个数据,这里默认提供了拍平成int,long,double的操作符
- limit 限流操作,比如数据流中有10个只要出前3个就可以使用
- distint 去重操作,对重复元素去重,底层使用了equals方法
- filter 过滤操作,把不想要的数据过滤
- peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等
- skip 跳过操作,跳过某些元素
- sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。

数据经过中间加工操作,就轮到终止操作符上场了;终止操作符就是用来对数据进行收集或者消费的,数据到了终止操作这里就不会向下流动了,终止操作符只能使用一次
collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors
count 统计操作,统计最终的数据个数
findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional
noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值

min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值
reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce
forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了
toArray 数组操作,将数据流的元素转换成数组。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值