java8新特性:三,Stream

1 Stream介绍

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

±-------------------+ ±-----+ ±-----+ ±–+ ±------+
| stream of elements ±----> |filter±> |sorted±> |map±> |collect|
±-------------------+ ±-----+ ±-----+ ±–+ ±------+
以上的流程转换为 Java 代码为:

List<Integer> transactionsIds =
widgets.stream().filter(b -> b.getColor() == RED).sorted((x,y) -> x.getWeight() - y.getWeight()).mapToInt(Widget::getWeight).sum();

2 什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:

Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

Stream可以由数组或集合创建,对流的操作分为两种:

1.中间操作:每次返回一个新的流,可以有多个。
2.终端操作:每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

Stream有以下几个特性:

1.stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
2.stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
3.stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

3.生成流

在 Java 8 中, 集合接口有两个方法来生成流:

stream() − 为集合创建串行流。

parallelStream() − 为集合创建并行流。

tips:java 字符串为空的情况

String a="";
String b=null;
System.out.println(a.isEmpty());
System.out.println(b.isEmpty());


生成流的例子:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class UseStream {public static void main(String[] args) {List<String> s= Arrays.asList("python"," ","xiaoxu","123","js","");System.out.println(s);System.out.println(s.getClass());System.out.println(s.stream().filter(str -> !str.isEmpty()));System.out.println(s.stream().filter(str -> !str.isEmpty()).collect(Collectors.toList()));System.out.println(s.stream().filter(str -> !str.isEmpty()).collect(Collectors.toList()).getClass());List<String> filtered=s.stream().filter(str -> !str.isEmpty()).collect(Collectors.toList());System.out.println(filtered);System.out.println(filtered.getClass());}
}


创建多种方式如下,stream可以通过集合数组创建:

1.通过java.util.Collection.stream(),java.util.Collection.parallelStream()用集合创建流

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;public class Mstream {public static void main(String[] args) {//1.通过java.util.Collection.stream(),java.util.Collection.parallelStream()创建List<String> s= Arrays.asList("a","b");//创建一个顺序流Stream<String> stream=s.stream();//创建一个并行流Stream<String> parallelStream=s.parallelStream();}
}

2.通过java.util.Arrays.stream(T[] array)方法用数组创建流:

import java.util.stream.IntStream;
import java.util.Arrays;int[] arr={1,5,7};
IntStream ints_tream=Arrays.stream(arr);

3.使用Stream的静态方法:of()、iterate()、generate()


import java.util.stream.Stream;Stream<Integer> i1=Stream.of(1,8,9);
Stream<Integer> i2=Stream.iterate(5,x->x+3).limit(4);
i2.forEach(System.out::println);
Stream<Double> i3=Stream.generate(Math::random).limit(3);
i3.forEach(System.out::println);
5
8
11
14
0.02766533296035878
0.779837131876051
0.6171275733047784

4.stream和parallelStream简单区分:stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,前提是流中的数据处理没有顺序要求。如果流中的数据量足够大,并行流可以加快处理度。

除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流:

import java.util.Arrays;
import java.util.List;
import java.util.Optional;List<Integer> ll=Arrays.asList(1,4,4,6);
Optional<Integer> k=ll.stream().parallel().filter(x->x==4).findFirst();
System.out.println(k.get());
4

5.Optional

Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

4 forEach

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

java中有多种方式对集合进行遍历,Collection.stream().forEach()和Collection.forEach()

4.1 增强for遍历集合

idea快捷导入类(import class),比如下面,在List后面光标,按下alt+enter,按下"import class",就会导入:import java.util.List
常见的java遍历集合的形式:增强for,输入a.for,idea快捷形成如下快捷方式:



4.2 函数式java:Collection.forEach()遍历集合

使用函数式JavaCollection.forEach()遍历:

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;public class ForEac {public static void main(String[] args) {List<String> a= Arrays.asList("A","D","C","E");Consumer<String> consumer_me= System.out::println;a.forEach(consumer_me);}
}


4.3 集合流上调用:Collection.stream().forEach()

public static void main(String[] args) {List<String> a= Arrays.asList("A","D","C","E");Consumer<String> consumer_me= System.out::println;a.forEach(consumer_me);a.stream().forEach(consumer_me);}


4.4 Parallel Stream

并发流允许我们在多个线程中执行stream,在这种情况下,执行顺序也不明确的。Java只需要在调用任何最终操作(例如Collectors.toList() )之前完成所有线程。

public class ForEac {public static void main(String[] args) {List<String> a= Arrays.asList("A","D","C","E");Consumer<String> consumer_me= System.out::println;a.forEach(consumer_me);
//        a.stream().forEach(consumer_me);System.out.println("-----------------");a.parallelStream().forEach(System.out::println);}
}

并发流,并不会按照插入顺序打印:

4.5 列表中使用的forEach()会使用自定义迭代器,而stream().forEach()只是从列表中逐个获取元素,会忽略迭代器

4.6 两个forEach()方法之间的另一个细微差别是Java明确允许使用迭代器修改元素。相反,stream不能。

4.7 例子:以下代码片段使用 forEach 输出了10个随机数

public static void main(String[] args) {Random random=new Random();System.out.println(random.ints());System.out.println(random.ints().limit(10));random.ints().limit(10).forEach(System.out::println);
}


5 map

map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数

public static void main(String[] args) {List<Integer> num= Arrays.asList(1,3,6,8,9,1);List<Integer> squareList=num.stream().map(i->i*i).distinct().collect(Collectors.toList());System.out.println(squareList);
}
[1, 9, 36, 64, 81]

6 filter

filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串

List<String> str=Arrays.asList("abc","","gh"," ","e");
List<String> fil_str=str.stream().filter(s->!s.isEmpty()).collect(Collectors.toList());
System.out.println(fil_str);
[abc, gh,  , e]

tips:因为字符串的isEmpty(),对于null来调用,会报空指针异常


所以在使用stream()的时候,要注意lambda方法中,异常数据是否会抛错的情况

7 limit

limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据

Random r=new Random();
r.ints().limit(10).forEach(System.out::println);


8 sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序

Random r=new Random();
r.ints().limit(10).sorted().forEach(System.out::println);


9 Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串

List<String> s= Arrays.asList("abc", "", "bc", "efg", "abcd"," ", "jkl");
List<String> fil=s.stream().filter(str->!str.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表:"+fil);
String st=s.stream().filter(str->!str.isEmpty()).collect(Collectors.joining(";"));
System.out.println("合并字符串:"+st);
筛选列表:[abc, bc, efg, abcd,  , jkl]
合并字符串:abc;bc;efg;abcd; ;jkl

10 统计

另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。

import java.util.*;public static void main(String[] args) {List<Integer> numbers=Arrays.asList(3,2,2,3,7,9,3);IntSummaryStatistics stats=numbers.stream().mapToInt(x->x).summaryStatistics();System.out.println("列表中最大的数:"+stats.getMax());System.out.println("列表中最小的数:"+stats.getMin());System.out.println("所有数之和:"+stats.getSum());System.out.println("平均数:"+stats.getAverage());}

java8新特性:三,Stream相关推荐

  1. 【java8新特性】——Stream API详解(二)

    一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...

  2. Java8新特性:Stream介绍和总结

    Java8新特性:Stream介绍和总结 什么是Stream 流(Stream)是数据渠道,用于操作数据源(集合.数组等)所生成的元素序列. 集合讲的是数据,流讲的是计算 注意: Stream自己不会 ...

  3. 使用Java8新特性(stream流、Lambda表达式)实现多个List 的笛卡尔乘积 返回需要的List<JavaBean>

    需求分析: 有两个Long类型的集合 : List<Long> tagsIds; List<Long> attributesIds; 现在需要将这两个Long类型的集合进行组合 ...

  4. java stream byte_乐字节-Java8新特性之Stream流(上)

    上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...

  5. Java8新特性-使用Stream流来实现递归遍历树形结构(案例)

    Java8新特性-Stream流 可能平常会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来 ...

  6. Java8新特性之Stream流式编程

    特地感谢鲁班大叔的分享,原学习地址:Java8 Stream流式编程爱 撸码就是快,流式编程好 代码传家宝 以下是学习过程整理的笔记 1.简介 Stream 流处理,首先要澄清的是 java8 中的 ...

  7. Java8新特性概览——Stream特性,Lambda表达式,函数式接口Function、Predicate、Consumer,方法引用等概述

    概述: Java 8 新特性概述:https://www.ibm.com/developerworks/cn/java/j-lo-jdk8newfeature/index.html JAVA8 十大新 ...

  8. Java8新特性:Stream详细使用

    目录 一.简介 二.创建Stream的常用方法 2.1 使用Stream中的静态方法:of().iterate().generate() 2.2 使用Collection下的 stream() 和 p ...

  9. Java8新特性之stream的详细用法

    一.概述 Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.使用Stream API 对集合数据进行操作,就类似于 ...

  10. Java8新特性之Stream流的使用

    Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找.过滤.筛选等操作,在新版的JPA中,也已经加入了Stream. 1.Stream的操作步骤 Stream有如下三个操 ...

最新文章

  1. 经典智力面试题:一家人过桥
  2. linux snmp设置报警次数,CentOS/RHEL 6下禁止重复的SNMP连接日志
  3. TweetLouder.com:在微博上找你喜好的乐队
  4. bat for循环_bat教程[279] reg import命令的用法
  5. CSS从大图中抠取小图完整教程(background-position应用)
  6. serviceloader java_【java编程】ServiceLoader使用看这一篇就够了
  7. 三相同步电机怎么接线图_智能电表怎么接线 单相 三相电表接线图大全
  8. 【译】响应式CSS动画
  9. 4.c++模式设计-建造者模式
  10. logstash java插件_[logstash-input-log4j]插件使用详解
  11. 使用Python编写Prometheus监控metrics接口
  12. 配置urlrewrite不生效
  13. 【企业微信】h5调试面板
  14. Linux驱动——mmc bus浅析(五)
  15. 用VS2010打开VS2013、VS2015、VS2017等高版本项目
  16. linux 服务器下查看防火墙
  17. Linux涂鸦智能网关面板Turnkey方案
  18. Cisco Packet Tracer(配置OSPF)
  19. c++ 汉字字符处理
  20. surface pro 将ubuntu安装在sd卡,并从sd卡启动

热门文章

  1. 【CSDN竞赛第10期】赢定制周边和《软件研发效能权威指南》实体书!
  2. 计算机软件版本如何命名,软件项目版本号的命名规则及格式
  3. flask+Vue基于web的旅游信息管理系统python django
  4. 2024考研风景园林专硕
  5. 常用计算机辅助系统,福师《计算机辅助设计1(PS)》在线作业一满分答案
  6. 【034】百度指数–实时百度热词搜索记录和用户画像
  7. 2022-- java发送http请求
  8. java斗图表情_程序员之间的斗图表情包, java真的输惨了!
  9. 《网上购物指南》的意义
  10. 阿里云域名解析完成后仍然无法通过域名正常访问网站