沉迷java_Java8 Stream系列(一)从入坑到沉迷

不想再用for嵌套for操作了,java8 带来了新的API —— Stream,非常强大!

Stream中文翻译成流,是一个支持串行和并行操作元素的序列,也是Lambda表达式配合使用的强大工具。

源码在java.util.stream中,感兴趣可以阅读阅读。

78330c679b60?from=timeline@

0x00 java8 中的流是什么

在编程中,对一串数据进行0个或者多个中间操作后,最后再获得结果。这个操作在没有流的情况下一般会涉及到多次循环,这是非常低效的。

流是为了处理一串数据(sequence),而不需要多次循环的一种方式。

流在操作序列的时候,会将数据放在一个叫Stream Pipeline的地方,这个地方会有三部分

源(一般为集合)

0或多个中间操作 (一般为惰性操作,不会直接操作数据)

终止操作 (一般为求最终值,这时流的整个流程结束)

流支持并行操作,而迭代器,for循环都是串行操作,所以流在多核处理上有强大优势。

78330c679b60?from=timeline@

流处理模型

1x00 Stream的类型和创建方式

创建流

// 从数组创建

int [] source = {1,2,3,4,5,6};

IntStream s = Arrays.stream(source);

// 从集合创建

List list = Arrays.asList(1,2,3,4,5);

Stream s2 = list.stream();

// 创建1到10的流

IntStream s3 = IntStream.range(1,10);

// 直接创建

Stream s4 = Stream.of("wo", "ai", "?")

其他流

此外,流还提供了几种包装好的流:

// 支持串行并行操作的序列,元素只有double类型的流

DoubleStream

// 支持串行并行操作的序列,元素只有int类型的流

IntStream

// 支持串行并行操作的序列,元素只有long类型的流

LongStream

2x00 常用的流方法

这里不过多提及,最好看一看API文档,我这里举一些常用的例子

// (惰性操作)中间操作,遍历

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

// (及早求值操作)终止操作,遍历

void forEach(Consumer super T> action)

例子:

// 将元素的平方打印出来

int[] nums = {2,3,4,5,6};

Arrays.stream(nums)

.map(i->i*i)

.forEach(System.out::println);

78330c679b60?from=timeline@

运行

// 将元素中的所有偶数累加求和

int[] nums = {2, 3, 4, 5, 6};

System.out.println(

Arrays.stream(nums)

.map(i -> i % 2 == 0 ? i : 0)

.reduce(0, Integer::sum)

);

78330c679b60?from=timeline@

运行结果

// flatMap处理嵌套的list

List> ll =

Arrays.asList(

Arrays.asList(1, 2, 3),

Arrays.asList(11, 22, 33),

Arrays.asList(0xF1, 0xF2, 0xF3)

);

ll.stream()

.flatMap(list -> list.stream())

.map(i -> 2 * i)

.forEach(i -> System.out.println(i));

78330c679b60?from=timeline@

运行结果

假设有N条营业数据,前5条是无关的测试数据,中间10条是要参加考核的,参与考核的需要知道其中超过50w(包括50)的数据的交易额平均值,其他不参与考核的忽略。

测试数据如下:

{11, 9, 2, 13, 1, 2, 99, 54, 23, 66, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2};

Stream trans = Stream.of(11, 9, 2, 13, 1, 2, 99, 54, 23, 66, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2);

IntSummaryStatistics all = trans

// 前5条跳过,2, 99, 54, 23, 66, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2

.skip(5)

// 取10条考核交易 2, 99, 54, 23, 66, 70, 23, 46, 50, 100

.limit(10)

// 将50以下的交易剔除 99, 54, 66, 70, 50, 100

.filter(i -> i >= 50)

// 转换成数字。如果是IntStream 则不需要转换

.mapToInt(i->i)

// 将流的统计结果放入包装对象中

.summaryStatistics();

// 交易总量 439w,平均值为439/6

System.out.println(all.getAverage());

78330c679b60?from=timeline@

运行结果

以上为流的一些基础使用方法。后续会有一些详细的补充,容我后面填坑。

3x00 流的特性

基于集合或者序列

流不存储值,也不能重复使用,数据通过管道的方式进行操作

每个操作都是函数式的,对流的操作不会影响源数据

多数操作(排序,映射,过滤等),可以延迟实现

基于集合和序列就不写例子了,不存储值也是一个概念,下面验证一下流不能重复使用。

3x01 不能重复使用

Stream trans = Stream.of(11, 9, 2);

trans.forEach(i -> System.out.println(i));

trans.reduce(0, Integer::sum);

当我第二次使用trans时,报错了。

78330c679b60?from=timeline@

运行结果

流只能使用一次,无法重复使用

3x02 验证流延迟操作

流只要在终止操作(及早求值)时,才会对数据统一做操作,在没有遇到求值操作的时候,惰性操作代码不会被执行。

Stream trans = Stream.of(11, 70, 23, 46, 50, 100, 10, 24, 18, 19, 2);

trans.map(i->{

System.out.println(i);

return i;

});

78330c679b60?from=timeline@

运行结果,上面都没打印

3x02 不影响源数据

可以创建一个List去实践,这里不写代码,当流执行完成之后,源List的数据是不会发生变化的

大家可以自己实践一下

流使用时注意点,我会在第二篇中更新,希望不会拖很久

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值