java8新特性 Stream API 开发参考

本文通过BaseStream和它的子接口,IntStream和Stream
BaseStream是java8 java.util.stream包下的接口,IntStream和Stream是BaseStream的子接口

Stream API的特性

stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果;
stream不会改变数据源,通常情况下会产生一个新的集合;
stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
对stream操作分为终端操作和中间操作。
终端操作:会消费流,这种操作会产生一个结果的,如果一个流被消费过了,那它就不能被重用的。
中间操作:中间操作会产生另一个流。
stream不可复用,对一个已经进行过终端操作的流再次调用,会抛出异常。

先上图:
在这里插入图片描述

父接口BaseStream的方法

两个泛型:T 用来指定流中存储数据的类型;S 另一个流的类型;
其中的close()方法就不用介绍了,是AutoCloseable接口中的方法。

方法名解释
boolean isParallel()如果调用的是一个并行流返回true,如果调用的是一个顺序流返回false;
Iterator<T> iterator()获得流迭代器,并返回对该迭代器的引用(终端操作)
S onClose(Runnable closeHandler)和close()有关,这里不介绍
S parallel()基于调用流,返回一个并行流(中间操作)
S sequential()基于调用流,返回一个顺序流 (中间操作)
Spliterator<T> spliterator()获取流的Spliterator ,并返回它的引用(终端操作)
S unordered()基于调用流,返回一个无序流,非并行流(中间操作)

代码演示:

iterator方法

用来串行的遍历流中的元素

int[] arr1 = {1,2,34,5};
BaseStream<Integer, IntStream> is = Arrays.stream(arr1);
Iterator it = is.iterator();
while(it.hasNext()){
    System.out.print(it.next() + " ");
}

运行结果:
1 2 34 5

spliterator方法

用来并行的遍历流中的元素
简单介绍一下用到的Spliterator接口中的方法:

方法名介绍
Spliterator trySplit()如果这个spliterator可以被分区,则返回一个包含元素的spliterator
boolean tryAdvance(Consumer<? super T> action)如果存在剩余元素,则对其执行给定操作,返回true;否则返回false。
public static void main(String[] args) {
    int[] arr2 = {1,2,3,4,5,6,7,8,9,10};
    BaseStream<Integer, IntStream> is = Arrays.stream(arr2);
    Spliterator<Integer> sit= is.spliterator();
    Spliterator<Integer> sit1 = sit.trySplit();
    Spliterator<Integer> sit2 = sit.trySplit();
    Thread t = new Thread( () -> {
        while(sit.tryAdvance(x -> System.out.println("sit :" + x))){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
    });
    Thread t1 = new Thread( () -> {
        while(sit1.tryAdvance(x -> System.out.println("sit1 :" + x))){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
    });
    Thread t2 = new Thread( () -> {
        while(sit2.tryAdvance(x -> System.out.println("sit2 :" + x))){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
    });
    t.start();
    t1.start();
    t2.start();
}

运行结果:

sit2 :6
sit1 :1
sit :8
sit1 :2
sit2 :7
sit :9
sit1 :3
sit :10
sit1 :4
sit1 :5

可以看到sit流中的数据{1,2,3,4,5,6,7,8,9,10}被分为sit1{1,2,3,4,5};sit2{6,7}和自己剩余的sit{8,9,10};

unordered

有时候取消流的顺序约束可以提高执行效率
打印有序流和无序流

Stream.of(5, 1, 2, 6, 3, 7, 4).unordered().forEach(x -> System.out.print(x + " "));
System.out.println("\n");
Stream.of(5, 1, 2, 6, 3, 7, 4).unordered().parallel().forEach(x -> System.out.print(x + " "));

运行结果:
5 1 2 6 3 7 4

3 6 4 7 5 2 1

IntStream和Stream都有的方法

以Stream为示

静态方法介绍
static <T> Stream.Builder<T> builder()一个用于Stream的可变生成器。
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)创建一个连接流,其元素为第一个流的所有元素,然后是第二个流的所有元素。
static <T> Stream<T> empty()返回一个空的顺序流
static <T> Stream<T> generate(Supplier<T> s)生成一个无限长度的无序流,这适用于生成恒定流和随机元素流。
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)返回一个无限长度的有序流,该流由函数f迭代应用到初始元素种子产生,产生一个由seed、f(seed)、f(f(seed))等组成的流。
static <T> Stream<T> of(T… values)返回一个顺序流,其元素为指定的值
static <T> Stream<T> of(T t)返回一个包含单个元素的顺序流。
方法介绍
Stream<T> filter(Predicate<? super T> predicate)Predicate接口是返回每个元素是否满足条件,filter函数将调用流中不满足条件的元素删去,返回一个新的流
<R> Stream<R> map(Function<? super T,? extends R> mapper)返回一个流,该流由对该流的元素应用给定函数的结果组成。
IntStream mapToInt(ToIntFunction<? super T> mapper)返回一个IntStream,该IntStream由将给定函数应用于该流元素的结果组成。
<U> Stream<U> mapToObj(IntFunction<? extends U> mapper)返回一个对象值流,该流由对该流的元素应用给定函数的结果组成。
mapToLong、mapToDouble不再介绍
<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)返回一个流,该流由对该流的元素应用给定函数的结果的多个流拼接组成。
Stream<T> distinct()返回由该流的不同元素组成的流(根据Object.equals(Object))。
Stream<T> sorted()返回一个由该流的元素组成的流,按自然顺序排序。
Stream<T> peek(Consumer<? super T> action)返回由该流的元素组成的流,另外,在使用结果流中的元素时对每个元素执行提供的操作。
Stream<T> limit(long maxSize)返回由该流的前maxSize元素组成的流
Stream<T> skip(long n)在丢弃流的前n个元素后,返回由该流的剩余元素组成的流。
void forEach(Consumer<? super T> action)对流的每个元素执行一个操作。(终端操作)
void forEachOrdered(Consumer<? super T> action)对流的每个元素执行一个操作,如果流有定义的相遇顺序,则按流的相遇顺序执行。
Object[] toArray()返回包含此流元素的数组。
reduce()使用关联累积函数对该流的元素执行缩减,并返回描述缩减值的可选值(如果有的话)。有三个重载,具体可参见这篇文章,这里就不在描述
<R,A> R collect(Collector<? super T,A,R> collector)使用收集器对该流的元素执行可变的缩减操作。下面的flatMap的代码中也用到了collect方法。具体可参见这篇文章
Optional<T> min(Comparator<? super T> comparator)根据提供的比较器返回流中的最小元素。
Optional<T> max(Comparator<? super T> comparator)根据提供的比较器返回该流的最大元素。
long count()返回此流中元素的计数。
boolean anyMatch(Predicate<? super T> predicate)返回此流的任何元素是否与提供的谓词匹配。
boolean allMatch(Predicate<? super T> predicate)返回此流的所有元素是否与提供的谓词匹配。
boolean noneMatch(Predicate<? super T> predicate)返回此流的任何元素是否与提供的谓词匹配。既就是anyMatch的值取反
Optional<T> findFirst()返回描述流的第一个元素的Optional实例,如果流为空则返回空Optional实例。
Optional<T> findAny()返回描述流的任意一个元素的Optional实例,如果流为空则返回空Optional实例。

其中mapToObj和mapToInt是两者互转的方法,并不是两个接口都有,只是放在一起说明而已

各种接口

  1. Supplier接口
Supplier s = new Supplier() {
    @Override
    public Object get() {
        return null;
    }
}
  1. UnaryOperator接口:
UnaryOperator u = new UnaryOperator() {
    @Override
    public Object apply(Object o) {
        return null;
    }
}
  1. Predicate接口
Predicate p = new Predicate() {
    @Override
    public boolean test(Object o) {
        return false;
    }
}
  1. Function接口
Function f = new Function() {
    @Override
    public Object apply(Object o) {
        return null;
    }
}
  1. ToIntFunction接口
ToIntFunction t = new ToIntFunction() {
    @Override
    public int applyAsInt(Object value) {
        return 0;
    }
}
  1. IntFunction接口
IntFunction i = new IntFunction() {
    @Override
    public Object apply(int value) {
        return null;
    }
}
  1. Consumer 接口
Consumer c = new Consumer() {
    @Override
    public void accept(Object o) {
        
    }
}
  1. Collector接口
Collector c = new Collector() {
    @Override
    public Supplier supplier() {
        return null;
    }

    @Override
    public BiConsumer accumulator() {
        return null;
    }

    @Override
    public BinaryOperator combiner() {
        return null;
    }

    @Override
    public Function finisher() {
        return null;
    }

    @Override
    public Set<Characteristics> characteristics() {
        return null;
    }
}
  1. Comparator 接口
Comparator c = new Comparator() {
    @Override
    public int compare(Object o1, Object o2) {
        return 0;
    }
}

代码示例(以Stream为示):

builder静态方法

build()方法是Builder内部接口中的方法,将Builder的对象转换成stream对象。
add()方法也是Builder内部接口中的方法,在Builder的对象中添加元素。

public static void main(String[] args) throws InterruptedException {
    Stream.Builder<String> builder = Stream.builder();

    Stream<String> stream = builder.add("GEEKS")
            .add("for")
            .add("Geeks")
            .add("GeEKSQuiz")
            .build();

    System.out.println(Arrays.toString(stream.toArray()));
}

运行结果:
[GEEKS, for, Geeks, GeEKSQuiz]

generate静态方法

参数是Supplier接口的实现,只有一个get()方法,无参数,返回值为Supplier申明的泛型。
打印5个10以内的整数随机数。

public static void main(String[] args) {
    Stream.generate(() -> new Random().nextInt(10))
            .limit(5).forEach(x -> System.out.print(x + " "));
}

输出结果:
3 3 0 8 5
打印10个相同数字

public static void main(String[] args) {
    Stream.generate(() -> 100).limit(5).forEach(x -> System.out.print(x + " "));
}

输出结果:
100 100 100 100 100

iterate静态方法、filter方法和map方法

打印0以后的10个奇数

public static void main(String[] args) {
    Stream.iterate(0, n -> n + 1)
            .filter(x -> x % 2 != 0) //odd
            .limit(10)
            .forEach(x -> System.out.print(x + " "));
}

运行结果:
1 3 5 7 9 11 13 15 17 19

打印从0开始的斐切那波数列的前20项

public static void main(String[] args) {
    Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0] + n[1]})
            .limit(20)
            .map(n -> n[0])
            .forEach(x -> System.out.print(x + " "));
}

运行结果:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

flatMap方法和map方法

public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        list1.add(1);list1.add(2);list1.add(3);
        list2.add(4);list2.add(5);
        List<List<Integer>> lists = new ArrayList<>();
        lists.add(list1);lists.add(list2);

        Stream stream = lists.stream().flatMap(new Function<List<Integer>, Stream<?>>() {
            @Override
            public Stream<?> apply(List<Integer> integers) {
                return integers.stream();
            }
        });
        Stream stream1 = lists.stream().map(new Function<List<Integer>, Stream<?>>() {
            @Override
            public Stream<?> apply(List<Integer> integers) {
                return integers.stream();
            }
        });
        System.out.println(stream1.collect(Collectors.toList()));
        System.out.println(stream.collect(Collectors.toList()));
    }

运行结果:
[java.util.stream.ReferencePipeline $ Head@4dd8dc3, java.util.stream.ReferencePipeline $Head@6d03e736]
[1, 2, 3, 4, 5]

可以看到,flatMap可以将List中的元素即List中的List转换为流然后将他们拼接成了一个流。
map处理的是List的中的元素,并没有把处理后的Stream拼接起来。

peek方法

在使用结果流中的元素时对每个元素执行提供的操作。
这样解释是因为peek是一个中间操作,单独调用并不会执行。需要调用终端操作时发生作用。

forEach和forEachOrdered比较

List<String> strs = Arrays.asList("a", "b", "c");
strs.stream().forEachOrdered(System.out::print);//abc
System.out.println();
strs.stream().forEach(System.out::print);//abc
System.out.println();
strs.parallelStream().forEachOrdered(System.out::print);//abc
System.out.println();
strs.parallelStream().forEach(System.out::print);//bca

anyMatch方法

找stream流中是否存在2

Stream<Integer> stream = Stream.of(1,1,1,3,1,5,6,1);
System.out.println(stream.anyMatch(x -> x == 2));

IntStream中的方法

静态方法介绍
static IntStream range(int startInclusive, int endExclusive)返回一个顺序有序的IntStream,从startInclusive(包括)到endExclusive(不包括),逐步递增1。
static IntStream rangeClosed(int startInclusive, int endInclusive)返回一个顺序有序的IntStream,从startInclusive(包括)到endExclusive(包括),逐步递增1。
方法介绍
OptionalDouble average()返回描述流中元素算术平均值的OptionalDouble,如果流为空则返回empty Optional。
IntSummaryStatistics summaryStatistics()返回一个IntSummaryStatistics,描述关于这个流元素的各种汇总数据。
LongStream asLongStream()返回由该流的元素组成的LongStream,并将元素类型转换为long。
DoubleStream asDoubleStream()返回由该流的元素组成的DoubleStream,并将元素类型转换为double。
Stream<Integer> boxed()返回一个由该流的元素组成的流,每个元素都被装箱为一个Integer。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脸是真的白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值