详细讲解新特性Stream流的使用

一、概念

stream流操作是Java 8提供一个重要新特性,它允许开发人员以声明性方式处理集合,其核心类库主要改进了对集合类的 API和新增Stream操作。Stream类中每一个方法都对应集合上的一种操作。将真正的函数式编程引入到Java中,能让代码更加简洁,极大地简化了集合的处理操作,提高了开发的效率和生产力。
同时stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O,channel等。在Stream中的操作每一次都会产生新的流,内部不会像普通集合操作一样立刻获取值,而是惰性取值 ,只有等到用户真正需要结果的时候才会执行。 并且对于现在调用的方法,本身都是一种高层次构件,与线程模型无关。因此在并行使用中,开发者们无需再去操心线程和锁了。Stream内部都已经做好了 。
关于对Stream流的理解,你可以把他当成工厂中的流水线,每个stream流的操作过程遵循着创建 -->操作 -->获取结果的过程,就像流水线上的节点一样组成一个个链条。除此之外你还可以把他理解成sql的视图,集合就相当于数据表中的数据,获取stream流的过程就是确定数据表的属性和元数据的过程,元数据的每一个元素就是表中的数据,对stream流进行操作的过程就是通过sql对这些数据进行查找、过滤、组合、计算、操作、分组等过程,获取结果就是sql执行完毕之后获取的结果视图一样,深入理解stream流可以让我们使用更加简洁的代码获取自己想要的数据。

二、创建流的方式

有几种方法可以创建流。它们可以从集合,数组,文件等创建。

2.1 从集合中创建流

在Java 8中,除了增加了很多Stream相关的类以外,还对集合类自身做了增强,在其中增加了stream方法,可以将一个集合类转换成流。

List<String> list= Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();

以上,通过一个已有的List创建一个流。

除此以外,还有一个parallelStream方法,可以为集合创建一个并行流。(多线程方式,需要考虑线程安全问题)

List<String> list= Arrays.asList("a", "b", "c");
Stream<String> stream = list.parallelStream();
 stream.forEach(item->{
    System.out.println(item);
 });

 可以看到,执行结果并不是a,b,c,是因为parallelStream会创建一个并行流,通过多个线程去处理流中的数据(也可能是主线程顺序执行),这样增加了流的处理方式,也正是因为是不同线程处理的数据,所以顺序发生了变化。

2.2 通过Sream创建流

可以使用stream类提供的of方法,直接返回一个由指定元素组成的流。 

Stream<String> stream = Stream.of("a","b","b");

三、Stream的中间操作

Stream的中间操作就像是一个流水线,在一个流上对每一个流过来的数据进行过处理,加工后得到的结果还是一个流。

 3.1 filter

filter方法用于通过设置的条件过滤出元素(用于过滤得到一个新的流)。下面举个例子,就是从原来的流串中将b字符串过滤掉。

public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b", "c");
        Stream<String> stream = list.stream();
        stream.filter(item->item!="b").forEach(System.out::println);
    }

3.2 concat

concat方法将两个Stream流连接在一起,合成一个Stream。若两个输入的Stream都是排序的,则新Stream也是排序的,若输入的Stream中任何一个是并行的,则新的Stream也是并行的,若关闭新的Stream时,则原两个输入的Stream都将执行关闭处理。

Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5))
       .forEach(integer -> System.out.print(integer + "  "));
// 1  2  3  4  5 


 List<String> list1 = Arrays.asList("10", "16", "30");
        List<String> list2 = Arrays.asList("15", "25", "50");

        Stream<String> stream1 = list1.stream();
        Stream<String> stream2 = list2.stream();
//        Stream<String> stream2 = list2.parallelStream();


        Stream<String> streamResult = Stream.concat(stream1, stream2);
        streamResult.forEach(System.out::println);

3.3 map

map方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素拼接一个2,相当于对流中的元素进行一个函数计算。 

List<String> list1 = Arrays.asList("10", "16", "30");
      
list1.stream().map(item-> item+2).forEach(System.out::println);

 3.4 flatMap

flatMap方法与map方法类似,都是将原Stream中的每一个元素通过转换函数转换,不同的是,该换转函数的对象是一个Stream,也不会再创建一个新的Stream,而是将原Stream的元素取代为转换的Stream。如果转换函数生产的Stream为null,应由空Stream取代。flatMap有三个对于原始类型的变种方法,分别是:flatMapToInt,flatMapToLong和flatMapToDouble。

List<Integer> list3 = Arrays.asList(1, 2, 3);
list3.stream().flatMap(integer -> Stream.of(integer *3)).forEach(System.out::println);

 3.5 peek

peek方法生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数,并且消费函数优先执行。

Stream.of(1, 2, 3, 4, 5)
        .peek(integer -> System.out.println("accept:" + integer))
        .forEach(System.out::println);
// accept:1
//  1
//  accept:2
//  2
//  accept:3
//  3
//  accept:4
//  4
//  accept:5
//  5

3.6 limit/skip

limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素。以下代码片段使用 limit 方法保理4个元素:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().limit(4).forEach(System.out::println);
//3,2,2,3

3.7 sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法进行排序:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().sorted().forEach(System.out::println);
//2,2,3,3,3,5,7

3.8 distinct

distinct主要用来去重,以下代码片段使用 distinct 对元素进行去重:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().distinct().forEach(System.out::println);
//3,2,7,5

四、Stream的最终操作

4.1 forEach

Stream 提供了方法 'forEach' 来迭代流中的每个数据。

4.2  count

count用来统计流中的元素个数。

4.3 collect

collect就是一个归约操作,可以接受各种做法作为参数,将流中的元素累积成一个汇总结果

        

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员Mapy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值