使用java8提供的stream api创建range

java的集合框架里没有range这个东西,大家都习惯于用三段式的for,鄙人用过其他的语言,觉得range确实是个不错的东西。 当然这个实现起来一点也不难,创建个list或array就行了,不过本文讲得是使用java8的stream。 为什么用stream呢,一是赶潮流,java8已经提供了部分函数式语言特征,stream就是这个部分中的重要一点,二是有一种懒加载的stream,使用list会使用大量内存,这个不需要,就跟三段式for一样多的内存就行(应该消耗大些,毕竟有个数据结构)。

我们先来了解stream,没有了解过java8的可能以为我说的这个stream是指io流,但这里的stream是java8提供的一种新的集合框架,有点类似于iterable,不过它的使用方式比较函数化,迭代操作不是使用传统或增强for,而是提供方法:例如forEach,方法接受的是函数式接口。 stream的创建不谈很多,就提出本文中需要的那个,Stream.generate(Supplier<T> s)这个方法 Supplier<T> 是个泛型接口,这个接口只有一个抽象方法(因为java8中接口允许有default方法,所以这里要强调是抽象方法),T get()。现在来写我们的range:

public class Range {


    public static Stream<Long> range(final long start,long length,int step) {
        Supplier<Long> seed = new Supplier<Long>() {

            private long next = start;

            @Override
            public Long get() {
                long _next = next;
                next += step;
                return _next;
            }
        };
        return Stream.generate(seed).limit(length);
    }

    public static void main(String[] args) {
        range(1,10,2).forEach(num -> {
            System.out.println(num);
        });
    }

}

range完成,经过测试,确实是懒加载的,注意我这里提供的第二个参数是长度,而不是end,这样少了很多判断(这些烦琐事交给别人),不过这里有个缺点,就是我们不能使用for循环,如果要使用就要将stream转换成collection,我没测试,但我估计这样就没有了懒加载。其实要实现可以进行增强for循环的range,应该实现一个iterable接口就行,这里扔以Stream为基础建立。
先放上代码吧。

public class Range implements Iterable<Long> {

    private Stream<Long> range;

    public Range(final long start,final long length,final int step) {
        Supplier<Long> seed = new Supplier<Long>() {

            private long next = start;

            @Override
            public Long get() {
                long _next = next;
                next += step;
                //System.out.println("get:"+next);
                return _next;
            }
        };
        range = Stream.generate(seed).limit(length);
    }



    public static void main(String[] args) {
        for (long next:new Range(1,10,1)){
            System.out.println(next);
        }
    }

    @Override
    public Iterator<Long> iterator() {
        return range.iterator();
    }
}

这里不再采用静态的方法去生成range。让Range类实现一个Iterable接口,因为这个接口只需要实现一个iterator方法,而Stream有一个默认方法iterator,经过测试这个也是懒加载形式,而且java8中为Iterable接口提供了默认的forEach方法,也就可以使用函数式了。当然我们可以自己去覆盖这个forEach, 直接使用stream的也行。注意覆盖接口中的默认方法,需要显示的写@Override,这里也倡导大家覆盖方法都写上这个annotation

    原文作者:247609107a39
    原文地址: https://www.jianshu.com/p/c1d6f2ccbe8b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞