【JAVA】JDK8-Stream

最近重新回顾jdk8,除了lambda表达式这种有趣的写法外,其中非常重要的两个特性,一个stream,一个函数式编程,今天先来讲讲stream;

一.引子

之前玩jdk8,stream在打印中,我碰到了一个异常错误,如下:
Exception in thread “main” java.lang.IllegalStateException: stream has already been operated upon or closed
该异常抛出时的原代码是这样的,

Stream stm = Stream.of("test", "123", "3");
stm.forEach(System.out::println);
System.out.println(stm.collect(Collectors.toList()));

如果干掉了第二步,则能正常打印,如下:

[test, 123, 3]

这就有意思了,从代码字面意思上来看,第二步是遍历打印元素,第三步是打印整个list,但是明显第二步影响了第三步的操作,这里面就要好好了解关于stream流的一些原理了。
关于该异常,根据异常信息,顾名思义,就是“流已操作或关闭”,换句话说,就是stream不能被复用,只能使用一次。这也符合流的定义,在servlet中的getInputStream只能获取一次(包括输入输出流)。

流的API设计使用了**管道(pipelines)**模式,对流的一次操作会返回另一个流,如同IO的API或者StringBuffer的append方法那样,从而可以使多个不同的操作在一个语句里串起来。

所谓的流,就是江河湖海,你在这一刻看到的流水下一次在同个地方就看不到了 ,同样是H20,但已经不是之前的那个它了!

抛砖引玉,我们继续讲一下stream的一些方法应用 :

二.方法

1.过滤(filter)

先看这样一段代码

Stream stm = Stream.of("test", "123", "3");

stm.filter(obj -> {
   System.out.println(obj);
   return true;
});

这段代码最后什么都没输出,在打印日志这里打断点,我们程序也不会进入。
相反,如果做下些许修改,如下:

Stream stm = Stream.of("test", "123", "3");

stm.filter(obj -> {
   System.out.println(obj);
   return true;
}).collect(Collectors.toList());

则最后会打印出

test 123 3

断点有效
再做些修改,如下:

Stream stm = Stream.of("test", "123", "3");

stm.filter(obj -> {
   System.out.println(obj);
   return true;
}).forEach(item -> System.out.println(item));

则最后会打印出

test test 123 123 3 3

断点有效

filter方法的参数是Predicate类型,forEach方法的参数是Consumer类型,它们都是函数接口。
如果不添加forEach等Consumer类型,仅仅Predicate,并不会生效,自然不会进入到方法中,编译不会报错,但运行无效。

2.限制条数(limit)

看到limit,首先就想到mysql中的limit取条数sql,整个开发语言中,无非就那么点单词,大同小异。
在stream流中,limit是一种常用方法,用于截取流中前n个的元素。
对应源码中的是:

Stream<T> limit(long maxSize);

注意 maxSize 不允许为负数,虽然编译无错,但运行中抛出 IllegalArgumentException 异常
先看下基本用法:

Stream stm = Stream.of("test", "123", "3");
stm.limit(2).forEach(obj -> System.out.println(obj));

打印结果:

test 123

3.跳过(skip)

skip,玩游戏的时候,看一些剧情,会有skip这样的字样,顾名思义,在stream流操作中,就是跳过前n个的意思。
它的用法跟limit一样,不允许为负数,对应源码中的是:

Stream<T> skip(long n);

示例用法:

Stream stm = Stream.of("test", "123", "3");
stm.skip(2).forEach(obj -> System.out.println(obj));

打印结果:

3

4.去重(distinct)

又是一个类数据库的方法名,在jdk8前,我们对一个集合比如list进行去重,会想到用set,因其自身的不允许重复的特性应用到去重操作中,但要list转化为set,还要写一些遍历方法,烦。jdk8太懂程序员的想法了,提供了distinct的方法。
其源码为:

Stream<T> distinct();

示例用法:

Stream stm = Stream.of("test", "123", "3", "3");
stm.distinct().forEach(obj -> System.out.println(obj));

打印结果:

test 123 3

  • 先到此,之后再写写函数式编程
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值