JAVA 8函数式编程(六):怎样复用Stream对象

在JAVA 8的Stream方法中,分为两大类,一类是惰性求值,另一类是立刻求值,只要Stream调用了立刻求值,Stream就会自动关闭,如果再次调用,将会提示如下错误:

java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
    at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:479)
    at com.mirana.stream.FlatMapReduceTest.testFlatMap(FlatMapReduceTest.java:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

这样的情况,就给我们摆出了一个难题,如果我们既要进行元素个数统计,又要对元素进行求和,两个立刻求值的函数,必然只能执行一个,怎么办呢?

查遍了Stream的官方接口,发现并没有解决此问题的方法,但是我们可以采用封装的方式解决此问题,即通过调用函数来获取新的Stream对象,从而分离Stream实例,如下:

private  List<String> joins = Lists.newArrayList("1, 2, 3", "2, 3, 4", "3, 4, 5");
//  通过函数每次返回新的Stream对象
public Stream<Integer> getStream() {
    //  将字符转换为数字Stream
    return joins.stream().flatMap(str -> {
        String[] nums = str.split(",");
        //  将字符转换为数字
        return Arrays.asList(nums).stream().map(num -> {
            return Integer.parseInt(num.trim());
        });
    });
}

从上面的例子可以看出:
1. Stream并没有依赖于可迭代对象的并发锁,只要调用stream()方法就会新的Stream实例,如上例中的joins对象可多次创建Stream实例,实例之间并没有相互影响;
2. flatMap方法与map方法的区别在于函数接口的返回值(注意,是函数接口,而不是方法自身,即Function.apply方法),flatMap必须返回Stream,而Map没有此限制;

如果要在函数内定义内调用,上述的方法还可以采用lambda的样式,如下:

@Test
public void testReStream() {
    //  直接在函数内定义函数
    Supplier<Stream<Integer>> supplier = () ->              joins.stream().flatMap(str -> {
        String[] nums = str.split(",");
        return Arrays.asList(nums).stream().map(num -> {
            return Integer.parseInt(num.trim());
        });
     });
    //  计数
    assertThat(supplier.get().count(), IsEqual.equalTo(9L));
    //  求和
    int sum = supplier.get().reduce((a, b) -> a + b).get();
    assertThat(sum, IsEqual.equalTo(27));
}

结论

JAVA 8的Stream类并没有直接提供复用的方法,只能采用封装的方式进行复用,所以也只是代码的复用,性能并没有提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值