[转载] Java8-Stream API 详解

参考链接: 如何在Java 8中从Stream获取ArrayList

摘要 

 Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。 

简介 

流(Stream)是数据通道,用于操作数据源(集合,数组等)所生成的元素序列 “集合讲的的是数据,流讲的是计算” 注意:  ① Stream不会存储元素  ② Stream不会改变源对象,相反他们会返回一个持有结果的新的Stream  ③ Stream操作是延迟执行的,这意味着他们等到需要结果的时候才会执行(惰性求值) 

Stream操作的三个步骤 

创建Stream 一个数据源(如:集合,数组)获取一个流中间操作 一个中间操作链,对数据源的数据进行处理终止操作(终端操作) 一个终止操作,执行中间操作链,并产生结果  

一:创建Stream 

Collection提供了两个方法.stream()与paralleStream() 

@org.junit.Test

public void test4(){

    List<Integer> list = new ArrayList<>();

    Stream<Integer> stream = list.stream();//串行流

    Stream<Integer> integerStream = list.parallelStream();//并行流

}

 

通过Arrays中的Stream()获取一个数组流。 

 Integer[] integers ={};

 Stream<Integer> stream1 = Arrays.stream(integers);

 

通过Stream类中静态方法of() 

Stream<String> stream2 = Stream.of("aaa", "bbb");

 

创建无限流(无穷的数据) 

  生成 //通过生成器产生5个10以内的随机数,如果不使用limit就会无限生成10以内随机数

Stream.generate(() -> Math.random() * 10).limit(5).forEach(System.out::println);

----------输出--------

0.8320556195819129

6.260534125204207

7.344094646332503

0.18490598959698068

6.392272744710005

 

  迭代 //通过迭代的方式(一元运算)生成5个数

Stream.iterate(0,x->x+2).limit(5).forEach(System.out::println);

-------------------输出------------

0

2

4

6

8

  

二:中间操作 

 

 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理,而在终止操作时一次性全部执行,称为“惰性求值” 

 List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().filter(x -> {

         System.out.println("函数执行");

         return x > 10;

 // stream3.forEach(System.out::println);

 

 上面的代码没有终止操作,当你运行时不会打印任何东西 

 

①筛选与切片 

filter----接收Lambda,从流中排除某些元素 

//filter()中需要使用断言型接口(Predicate)

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().filter(x -> x > 10);

stream3.forEach(System.out::println);

 

limit----截断流,使其元素不超过给定数量 

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().limit(3);

stream3.forEach(System.out::println);

--------------------输出---------------------

1

2

3

 

skip----跳过元素返回一个抛弃了前n个元素的流,若流中元素不满足n个,则返回一个空流,与limit形成互补 

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().skip(3);

stream3.forEach(System.out::println);

--------------------输出---------------------

523

21

55

 

distinct----筛选,通过流所所生成元素的hashCode()和equals()去除重复元素 

  List<Integer> list = Arrays.asList(1,2,3,3,2,4);

  Stream<Integer> stream3 = list.stream().distinct();

  stream3.forEach(System.out::println);

  --------------------输出---------------------

  1

  2

  3

  4

 

注意:自定义的实体类使用distinct去重时,一定要先重写hashCode()和equals() 

②映射 

map----接收Lambda,将元素转换为其他形式或提取信息时,接收一个函数作为参数,该函数被应用到每个元素上,并将其映射成一个新的元素//map()里面使用函数型接口(Function)

List<String> list = Arrays.asList("aa","bb","cc");

Stream<String> stream3 = list.stream().map(String::toUpperCase);

stream3.forEach(System.out::println);

----------------------输出-----------------------

AA

BB

CC

------------------------------------------------

集合里的每一个元素都会使用到String.toUpperCase()方法

它是以aa作为一个元素,bb作为一个元素 

 flatMap----接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接一个流List<String> list = Arrays.asList("aa","bb","cc");

       Stream<String> stream3 = list.stream().flatMap(l -> {

           String[] strings = l.split("");

           return Arrays.stream(strings);

       });

stream3.forEach(System.out::println);

-------------------输出-----------

a

a

b

b

c

c

-----------------------------------------------

flatMap将原来的流转换为一个新的流并且,是以每一个值为单位的

 

   

    

    

③排序 

sorted() 自然排序 按照Comparable的方式List<String> list = Arrays.asList("aa","cc","bb");

Stream<String> stream3 = list.stream().sorted();

stream3.forEach(System.out::println);

---------------输出-----------

aa

bb

cc

 sorted( Comparator com)定制排序 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 Stream<Integer> stream3 = list.stream().sorted(Integer::compare);

 stream3.forEach(System.out::println);

 --------------输出--------------

 1

 2

 3

 3

 6

 8

 9

  

终止操作 

①查找与匹配 

allMatch----检查是否匹配所有元素//allMatch()里面的时断言型接口(Predicate)

 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 boolean b = list.stream().allMatch(x -> x > 3);

 System.out.println(b);

 ------------------输出--------------------

 false

 //因为不是所有的数都大于3

 anyMatch----检查是否有匹配至少一个元素//anyMatch()里面的时断言型接口(Predicate)

 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 boolean b = list.stream().anyMatch(x -> x > 3);

 System.out.println(b);

  ------------------输出--------------------

 true

 //只要有大于3的数就返回true

 noneMatch----检查是否没有匹配的元素//noneMatch()里面的时断言型接口(Predicate)

List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

boolean b = list.stream().noneMatch(x -> x > 3);

System.out.println(b);

 ------------------输出--------------------

 false

 //双重否定,返回false就是有匹配的元素

 findFirst----返回第一个元素List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> first = list.stream().findFirst();

System.out.println(first.get());

-----------------输出----------------

1

 findAny----返回当前流中的任意一元素List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> first = list.stream().findAny();

System.out.println(first.get());

-----------------输出----------------

1

 count-----返回流中元素的总数List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

long count = list.stream().count();

System.out.println(count);

-----------------输出----------------

7

 max----返回流中最大值 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 Optional<Integer> max = list.stream().max(Integer::compareTo);

 System.out.println(max.get());

 -----------------输出----------------

9

 min----返回流中的最小值List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> min = list.stream().min(Integer::compareTo);

System.out.println(min.get());

 -----------------输出----------------

1

 forEach----遍历流中的元素 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 list.stream().forEach(System.out::println);

 -----------------输出----------------

1

3

2

6

8

3

9

//注意:forEach的迭代操作是由Stream API完成的称为内部迭代

//借助于iterator的方式为外部迭代

  

②归约 

reduce(T identity,BinaryOperator)—可以将流中元素反复结合起来得到一个值,返回T List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 Integer reduce = list.stream().reduce(0, (x, y) -> x + y);

 System.out.println(reduce);

 -----------------输出----------------

 32

 //根据2元运算将所有的数加起来

 //首先以0为x,1为y,结果为1,然后1为x,取3为y,结果为4,以4为x...以此类推

 reduce(BinaryOpreator)----可以将流中元素反复结合起来,返回Optional< T > List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

 Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);

 System.out.println(reduce.get());

  -----------------输出----------------

 32

 //原理同上,只是这里没有初始值,直接取1为x

 //所以ist就有可能为空,当返回的值可能为空时,结果存储在Optional容器中,避免空指针异常

  

③收集 

collect----将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法 

 

 Colloector 接口中方法的实现决定了如何对流执行手机操作(如收集到List、Set、Map中)但是Collectots实用类提供了很多静态方法,可以方便的创建常见收集器实例 

 

接下来进行详细介绍 首先创建一个实体类 

public class User {

    private String name;

    private Integer age;

    private double salary;

 

    public User(String name, Integer age, double salary) {

        this.name = name;

        this.age = age;

        this.salary = salary;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public Integer getAge() {

        return age;

    }

 

    public void setAge(Integer age) {

        this.age = age;

    }

 

    public double getSalary() {

        return salary;

    }

 

    public void setSalary(double salary) {

        this.salary = salary;

    }

 

    @Override

    public String toString() {

        return "User{" +

                "name='" + name + '\'' +

                ", age=" + age +

                ", salary=" + salary +

                '}';

    }

 

    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        return Double.compare(user.salary, salary) == 0 &&

                Objects.equals(name, user.name) &&

                Objects.equals(age, user.age);

    }

 

    @Override

    public int hashCode() {

        return Objects.hash(name, age, salary);

    }

}

 

在测试类中准备好数据 

public class StreamTest {

     List<User> user = Arrays.asList(new User("张三",12,1000.00),

                                    new User ("李四",32,4000),

                                    new User ("王五",40,4000),

                                    new User ("王五",40,4000));

}

 

根据名称生成一个新的List 

 List<String> list = user.stream().map(User::getName).collect(Collectors.toList());

 list.forEach(System.out::println);

 -----------------输出--------------

 张三

 李四

 王五

 王五

 

根据名称生成一个新的Set 

 Set<String> set = user.stream().map(User::getName).collect(Collectors.toSet());

 set.forEach(System.out::println);

 -----------------输出--------------

 张三

 李四

 王五

 

根据名称生成一个新的HashSet 

 HashSet<String> hashSet = user.stream().map(User::getName).collect(Collectors.toCollection(HashSet::new));

 hashSet.forEach(System.out::println);

 -----------------输出--------------

 李四

 张三

 王五

 

获取流中的元素总数 

Long count = user.stream().collect(Collectors.counting());

System.out.println(count);

-----------------输出--------------

4

 

根据工资获取平均值 

Double avg = user.stream().collect(Collectors.averagingDouble(User::getSalary));

System.out.println(avg);

-----------------输出--------------

3250.0

 

根据工资获取总和 

Double sum = user.stream().collect(Collectors.summingDouble(User::getSalary));

System.out.println(sum);

-----------------输出--------------

13000.0

 

根据工资获取组函数 

 DoubleSummaryStatistics sum = user.stream().collect(Collectors.summarizingDouble(User::getSalary));

 System.out.println(sum);

 -----------------输出--------------

 DoubleSummaryStatistics{count=4, sum=13000.000000, min=1000.000000, average=3250.000000, max=4000.000000}

 

根据工资获取最大值 

 Optional<User> max = user.stream().collect(Collectors.maxBy(Comparator.comparingDouble(User::getSalary)));

 System.out.println(max.get());

 -----------------输出--------------

 User{name='李四', age=32, salary=4000.0}

 

根据工资获取最小值 

 Optional<User> min = user.stream().collect(Collectors.minBy(Comparator.comparingDouble(User::getSalary)));

 System.out.println(min.get());

 -----------------输出--------------

 User{name='张三', age=12, salary=1000.0}

 

分组 

Map<Double, List<User>> map = user.stream().collect(Collectors.groupingBy(User::getSalary));

System.out.println(map);

-----------------输出--------------

{4000.0=[User{name='李四', age=32, salary=4000.0}, User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}], 1000.0=[User{name='张三', age=12, salary=1000.0}]}

 

多级分组 

Map<Double, Map<String, List<User>>> collect = user.stream().collect(Collectors.groupingBy(User::getSalary, Collectors.groupingBy(

                u -> {

                    if ( u.getAge() <= 12) {

                        return "青年";

                    } else if ( u.getAge() <= 32) {

                        return "中年";

                    } else {

                        return "老年";

                    }

                }

        )));

System.out.println(collect);    

-----------------输出--------------    

{4000.0={老年=[User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}], 中年=[User{name='李四', age=32, salary=4000.0}]}, 1000.0={青年=[User{name='张三', age=12, salary=1000.0}]}}

 

分区 

Map<Boolean, List<User>> collect1 = user.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 3000));

System.out.println(collect1);

-----------------输出--------------   

{false=[User{name='张三', age=12, salary=1000.0}], true=[User{name='李四', age=32, salary=4000.0}, User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}]}

 

连接 

String s = user.stream().map(User::getName).collect(Collectors.joining("--"));

System.out.println(s);

-----------------输出--------------

张三--李四--王五--王五

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540148.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Microsoft System Center中利用您的现有投资管理VMware--Veeam MP v6.5

在 Microsoft System Center 中利用您的现有投资管理 VMware VeeamManagement Pack (MP) v6.5 适用于物理、虚拟和备份基础架构的单一的虚拟管理平台 前段时间介绍了Veeam Management Pack (MP) v6.0产品&#xff0c;昨天发布了新版本VeeamManagement Pack (MP) v6.5&#xff0…

[转载] Java关键字(Java 8版本)

参考链接&#xff1a; 所有Java关键字列表 定义 被Java语言赋予了特殊含义&#xff0c;用作专门用途的字符串&#xff08;单词&#xff09;&#xff0c;这些关键字不能用于常量、变量、和任何标识符的名称。 Java关键字(Java 8版本) Java关键字(Java 8 以后版本) 注意事…

uiw 1.2.17 发布,基于 React 16 的组件库

发布&#xff0c; 高品质的UI工具包&#xff0c;React 16的组件库。 文档网站&#xff1a;uiw-react.github.io开源仓库&#xff1a;github.com/uiw-react/u… 更新内容&#xff1a; ? 修复没有代码检测文件匹配*.css。 5712887 ? 添加 .editorconfig 文件. d82dabf ⛑ 给测试…

[转载] Java中this和super关键字分别是什么意思

参考链接&#xff1a; Java中的Super关键字 this和super关键字 this是自身的一个对象&#xff0c;代表对象本身可以理解为指代当前的对象&#xff0c;它可以调用当前对象的属性、方法和构造方法&#xff0c;一般情况下可以省略&#xff0c;必须使用this的地方是区分出现名字重…

SpringMVC注解HelloWorld

今天整理一下SpringMVC注解 欢迎拍砖 RequestMapping RequestMapping是一个用来处理请求地址映射的注解&#xff0c;可用于类或方法上。用于类上&#xff0c;表示类中的所有响应请求的方法都是以该地址作为父路径。 RequestMapping注解有六个属性&#xff0c;下面我们把她分成三…

mysql问答汇集

问:A&#xff0c;B两台mysql实现主从复制,A提供写&#xff0c;B提供读,那既然B要同步A&#xff0c;当A更新数据的时候&#xff0c;B不也一样要更新吗&#xff1f;那B不还是没有实现负载减轻吗&#xff1f;还有能通过MYSQL proxy实现3台mysq均衡l吗&#xff1f;一台写&#xff0…

自制 移动端 纯原生 Slider滑动插件

在Google搜关键字“slider”或“swiper”能找到一大堆相关插件&#xff0c;自己造轮子是为了能更好的理解其中的原理。 给这个插件取名为“veSlider”是指“very easy slider”非常简单的一个滑动插件。 这只是个半成品&#xff0c;仅仅实现了手指滑动、自动轮播、跳转等基本功…

ISA Server 2006 部署步骤

ISA Server 2006 部署步骤 Posted by 尹揆 在这里先把ISA2006的安装步骤给大家贴出来,后面陆续会有一些配置及日常的应用,希望大家多多指教!呵呵.ISA功能的强大自然不用多说了,一句话只要能想到它就能做到!放入光盘出现在我们面前还是其人性化的界面点默认的下一步吧接受协议序…

ELK 分析 nginx access 日志

注意&#xff1a;修改配置后建议重新创建index 1、nginx 日志文件格式 123log_format elk "$http_clientip | $http_x_forwarded_for | $time_local | $request | $status | $body_bytes_sent | ""$request_body | $content_length | $http_referer | $http_use…

mysql将查询数据另存

1.查询mysql的存储执行目录&#xff08;secure-file-priv是指定文件夹作为导出文件存放的地方&#xff09;所以需要查询以下&#xff0c;不然会报1290错误 show variables like %secure%;2.查询并转存 SELECT * into outfile C:\ProgramData\MySQL\MySQL Server 5.7\Uploads\zo…

重新捡起flask(三)

记一次bug调试。 本来以为模板这一章可以很快的过掉的&#xff0c;刚刚写完的2其实只剩下个flask-moment时间库了&#xff0c;之前早就做过&#xff0c;记得很简单&#xff0c;本来说只要敲一下代码就结束&#xff0c;没想到&#xff0c;踩坑里去了。 调试bug吗&#xff0c;我想…

远程服务器部署spring boot 项目(centos7为例)

1.打包项目&#xff08;可以是jar包&#xff0c;也可以是war包&#xff09;以jar包为例&#xff08;用eclipse打包&#xff09;&#xff1a;1.项目目录右击--debug as&#xff08;run as&#xff09;--maven build&#xff0c;然后输入package&#xff0c;点击debug&#xff0c…

SIN的服务器配置

统计了新加坡服务器中IBM XIV存储挂载的主机列表。 对于vmware虚拟机来说&#xff0c;是这么组成的&#xff1a; 存储分了多个lun&#xff0c;在os侧叫做data store&#xff0c;多个datastore挂给多个物理机&#xff0c;物理机(安装了esxi软件)称为ESXI主机&#xff0c;多个ESX…

sklearn的train_test_split

sklearn的train_test_split train_test_split函数用于将矩阵随机划分为训练子集和测试子集&#xff0c;并返回划分好的训练集测试集样本和训练集测试集标签。 格式&#xff1a; X_train,X_test, y_train, y_test cross_validation.train_test_split(train_data,train_target,…

textmate bundle for jquery

使用这个bundle的例子:键入ready然后按tab就会生成下面的代码:$(document).ready(function() { }); 其中第二行被选中,这时在里面编写jquery代码即可. 如果要查看某个function的官方文档的话可以在键入的function之后使用快捷键ctrlh 查看. 关于bundle的下载 这里是一个textmat…

sklearn机器学习实例

原创网址&#xff1a;https://blog.csdn.net/qq_27150893/article/details/80169736 sklearn是非常流行的机器学习库&#xff0c;实现了很多的机器学习模型。官网&#xff1a;http://scikit-learn.org/stable/ 里面有全面的实例和模型参数讲解&#xff0c;用到哪个模型就去官…

CSVDE批量导入域用户

CSVDE批量导入用户 你可以使用Csvde格式的文件在活动目录中创建用户帐号和其他类型的帐号。但你不能使用Csvde删除活动目录中的对象。 使用Csvde命令行工具创建用户帐号&#xff0c;采用下列步骤&#xff1a; 1. 创建Csvde输入文件。文件应包含下列信息。 属性行&#xff1a;这…

sklearn 实例

http://scikit-learn.org/stable/auto_examples/index.html sklearn例子大全 https://deeplearning4j.org/mnist-for-beginners deeplearning官网

pip 安装模块时报“pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonh”

连接镜像网站即可 以豆瓣镜像为例&#xff1a; 解决方案&#xff1a; pip install grpcio-tools -i https://pypi.doubanio.com/simple 后面的-i https://pypi.doubanio.com/simple即是镜像 镜像站推荐&#xff1a; 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科…

【转载】细聊冗余表数据一致性(架构师之路)

本文主要讨论四个问题&#xff1a; &#xff08;1&#xff09;为什么会有冗余表的需求 &#xff08;2&#xff09;如何实现冗余表 &#xff08;3&#xff09;正反冗余表谁先执行 &#xff08;4&#xff09;冗余表如何保证数据的一致性 一、需求缘起 互联网很多业务场景的数据量…