Java函数式编程(三)Stream与List的区别和创建

之前看一本关于JDK8的书,推荐stream的一个理由是,是stream经过优化的可以发挥多核处理器的优势(忘了,但大概印象是多核)充分利用设备资源。所以说stream除了简化编程代码,实际上也提高了效率。

在没看资料之前,我使用stream都是网上找例子,比如去搜索“如何List转换成map这种”。在梳理了资料后,感觉对stream的写法有了一个新的认识。

一 stream到底是什么
看起来stream像是一个数据结构来存数据的,实际并不是,就拿我们日常见得最多的List作比较。首先List你要创建后往里面赛数据,实际上他的大小不是无限的,因为不可能创建一个无穷大的队列。但stream可以装进去“无数个元素”。

比如我们说自然数是无穷无尽的,我们可以创建一个自然数的stream,当然这个创建自然数的规则暂时不具体实现

Stream<BigInteger> naturals = createNaturalStream();

但是你要输出这个的话,不可能让你无穷无尽的输出,你要给定一个范围才能输出。

Stream<BigInteger> naturals = createNaturalStream()limit(100) .forEach(System.out::println);

所以说stream相当于保存了一个规则,用的时候根据规则再计算。

说到这里,我还要知道一个概念就是,链式操作。有的地方也说是链式编程,说stream的写法很符合链式操作。所谓的链式操作,说的直白点就是所有的操作像一个链条一样,一个接一个的。

比如

obj.methodA().methodB().methodC().methodD()......;

二 Stream的创建
看了前面的部分,发现这个stream和我们之前使用的Collection集合压根是两回事,它类似一个公式,到用的时候直接根据公式输出,过滤或者其他操作,但是他不一定存储元素在里面。

(1)Stream.of()
这个方法其实类似我们刚开始初始化数组,或者集合一样,直接给定一些元素创建

 Stream<String> stream = Stream.of("ZP_is_handsome", "ZP_is_smart", "ZP_is_best");

(2)基于数组和Collection
这种类似初始化的创建stream用到的机会很少,主要的还是要和数据和Collection打交道,比如说把某个数组,或者列表转换成一个stream。

 String[] testArrays = {  "ZP_is_handsome","ZP_is_clever","ZP_has_talent"  };

 Stream streamArray = Arrays.stream(testArrays);
        
 List<String> list = Arrays.asList(testArrays);
 Stream streamList = list.stream();
 streamArray.forEach(System.out::println);
  streamList.forEach(System.out::println);

(3)通过Supplier来生成
以上都是提供好元素,或者给个数组集合自己转换成stream。实际上这些都是有限的stream,我们之前说stream可以无限的,怎样生成一个“无限”大的stream,可以通过function包下面的Supplier来生成。

实际上这个Supplier是一个接口,具体怎么实现还要靠你如何定义实现。

Supplier的源码

package java.util.function;

/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

以下是一个例子

 @Test
    public void createStreamBySupplier(){
        Stream<Integer> natual = Stream.generate(new NatualSupplier());
        // 注意:无限序列必须先变成有限序列再打印:
        natual.limit(20).forEach(System.out::println);
    }
class NatualSupplier implements Supplier<Integer> {
    int n = 0;
    public Integer get() {
        n++;
        return n;
    }
}

一下是一个我该写的一个的斐波那契数列的demo

package com.example.zp.demo.testDemo;

import org.junit.jupiter.api.Test;

import java.util.function.LongSupplier;
import java.util.stream.LongStream;

public class FibonacciStream {
    @Test
    public void generateFibonacciStream(){
        //实际上斐波那契:实际上就是a(n) = a(n-1) + a(n-2),非常递归的一个形式
        LongStream fib = LongStream.generate(new FibSupplier());
        // 打印Fibonacci数列:1,1,2,3,5,8,13,21...
        fib.limit(10).forEach(System.out::println);
    }
}

class FibSupplier implements LongSupplier {
    int n = 0;

    /**
     * 用递归实现斐波那契数列
     * @param i 需要得到的第i项
     * @return 第i项内容
     */
    public static int fibonaccis(int i){
        if(i == 1 || i == 2){
            return 1;
        }else{
            return fibonaccis(i-1) + fibonaccis(i - 2);
        }
    }

    public long getAsLong() {
        n++;
        return fibonaccis(n);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值