java8 Stream API详解

一、Stream流概述

1、java8中有两大最为重要的改变,第一就是Lambda表达式,另一个则是Stream API。

2、Stream API真正把函数式编程风格引入到Java中。这是目前为止,java类库中最好的补充,因为Stream API可以极大地提高java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

3、Stream是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤、和映射数据库等操作。使用Stream API对集合进行的操作是在java层面进行的,就类似于使用SQL执行的数据库查询操作,也可以使用Stream进行并行操作。

4、为什么要学习Stream API?

实际开发中,项目中很多数据源都是来源于Mysql、Oracle等关系型数据库,但对于MongDB、Redis等非关系型数据库查询出来的数据就需要在java层面进行处理。

5、Stream和Collection集合的区别:

集合的增删改查操作是在数据结构(内存)层面进行的,数据源会随之发生改变;

Stream操作是在数据(CPU)层面进行的,数据源不会随之发生改变。

6、图解Stream

img

7、使用Stream的步骤:

(1)产生一个流(Stream),

​ 一个数据源,获取一个流;

(2)中间链式(流水线式)操作,

​ 一个中间的操作链,对数据源的数据进行处理;

(3)产生一个新流,

​ 一个终止操作,执行中间操作链,产生结果。

注意:Stream操作是延迟执行的,他们会等到需要结果时才会执行。

二、创建Stream的方式

  • 相关API

img

  • 具体事例
public static void main(String[] args) {//1.Collection中的方法Collection<Integer> collection = new ArrayList<>();Stream<Integer> stream = collection.stream();Stream<Integer> stream1 = collection.parallelStream();//2.Arrays中的stream方法(静态方法,可直接调用)IntStream stream2 = Arrays.stream(new int[]{1, 2, 3});//3.Stream中的of方法(静态方法,可直接调用)Stream<String> stream3 = Stream.of("as", "cx1", "323");//4.Stream中的方法-创作无限流(结果有无限多个)/*** 4.1 iterate : 这里的例子可理解为,从2开始,每隔2产生一个数据,总共产生无穷多个* iterate的第二个参数是UnaryOperator,它是一个接口,继承内置函数型接口Function* public interface UnaryOperator<T> extends Function<T, T>*  此处使用Lambda表达式以及方法引用*/Stream<Integer> stream4 = Stream.iterate(2, x -> x + 2);stream4.forEach(System.out::println);/*** 4.2 generate:* public static<T> Stream<T> generate(Supplier<T> s)* 参数是内置供给型接口Supplier* 此处使用Lambda表达式以及方法引用*/Stream<Double> stream5 = Stream.generate(() -> Math.random());stream5.forEach(System.out::println);}

三、Stream的中间操作

筛选与切片

  • filter
  • Stream filter(Predicate<? super T> predicate);
  • 接收Lambda,从中排除某些元素,参数是内置断定型接口Predicate,
  • 需要特别注意的是:Stream操作的“延迟加载”或叫“惰性加载”:只有执行终止操作,中间操作才会被执行。例子中进行了验证。
public class FilterTest {private static List<Student> stuList;static {stuList = Arrays.asList(new Student(1, "zhangsan1", 12, 171.1, 3001D),new Student(2, "zhangsan1", 14, 172.1, 4001D),new Student(3, "zhangsan1", 16, 173.1, 5001D),new Student(4, "zhangsan1", 18, 174.1, 6001D),new Student(5, "zhangsan1", 20, 175.1, 7001D),new Student(6, "zhangsan1", 21, 176.1, 8001D),new Student(7, "zhangsan1", 22, 177.1, 9001D));};@Testpublic void test01(){//1.创建Stream流Stream<Student> s1 = stuList.stream();//2.中间操作,找年龄大于18岁的学生Stream<Student> studentStream = s1.filter(x -> x.getAge() >= 18);//3.终止操作studentStream.forEach(x-> System.out.println(x.getAge()));}/*** 注意如果只执行1、2,不执行终止操作,则不会输出任何结果* 证明Stream操作的“延迟加载”或叫“惰性加载”:只有执行终止操作,中间操作才会被执行*/@Testpublic void test02(){//1.创建Stream流Stream<Student> s1 = stuList.stream();//2.中间操作,找年龄大于18岁的学生Stream<Student> studentStream = s1.filter(x -> {System.out.println("正在执行过滤.......");return x.getAge() >= 18;});//3.终止操作//studentStream.forEach(x-> System.out.println(x.getAge()));}/*** 链式操作*/@Testpublic void test03(){stuList.stream().filter(x -> x.getAge() >= 18).forEach(x-> System.out.println(x.getAge()));}
}
  • limit
  • Stream limit(long maxSize)
  • 截断流,使其长度不能超过给定数量。方法短路,效率高。
    @Testpublic void test04(){stuList.stream().limit(3).forEach(System.out::println);}
  • skip
  • Stream skip(long n)
  • 跳过元素,返回扔掉了前n个元素的流,如果流中元素不足n,则返回一个空流。
    @Testpublic void test04(){stuList.stream().skip(3).forEach(x->System.out.println(x.getName()));}
  • distinct
  • Stream distinct()
  • 筛选,根据流所生成元素的hashCode和equals方法去掉重复元素。所以如果使用的是引用类型,需要重写hashCode和equals。
  • 方法重写
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Student)) return false;Student student = (Student) o;return Objects.equals(getId(), student.getId()) &&Objects.equals(getName(), student.getName()) &&Objects.equals(getAge(), student.getAge()) &&Objects.equals(getHeight(), student.getHeight()) &&Objects.equals(getSalary(), student.getSalary());}@Overridepublic int hashCode() {return Objects.hash(getId(), getName(), getAge(), getHeight(), getSalary());}
  • 具体事例
static {stuList = Arrays.asList(new Student(1, "zhangsan1", 12, 171.1, 3001D),new Student(1, "zhangsan1", 12, 171.1, 3001D),new Student(3, "zhangsan3", 16, 173.1, 5001D),new Student(4, "zhangsan4", 18, 174.1, 6001D),new Student(5, "zhangsan1", 20, 175.1, 7001D),new Student(6, "zhangsan6", 21, 176.1, 8001D),new Student(7, "zhangsan7", 22, 177.1, 9001D));
}@Test
public void test04(){stuList.stream().distinct().forEach(System.out::println);
}

映射

map:接收Lambda,将元素转换成其他形式或提取信息。接收一个参数,该参数会被应用到每个元素上,并将其映射成一个新的元素。

可以通俗的理解成数学中的函数,输入x,将x映射成相应的y,并返回覆盖原来的x,从而形成新的元素。

  • 案例1:将字符串中的小写变大写

img

  • 案例2:只获取学生姓名

img

  • 案例3:获取年龄大于18岁的学生的名字

img

排序

img

  • sorted

自然排序:底层根据内部比较器进行排序——>Conparable接口——>comparaTo方法

img

  • 指定sorted排序策略

指定排序策略:底层根据外部比较器进行比较排序——>Comparator接口——>一定要自己重写compare方法来指定比较规则。

img

img

四、终止操作

第一大类API(太过简单)

img

img

第二大类AP

用法大同小异,都不难。

*但,需要注意的是,一部分先查找后返回的API,采用的是Optional进行接收。因为查找的结果有可能是空集合。*

img

具体实例:

img

img

img

img

img

归约

终止操作中稍微有点难理解的的就是归约。

  • 归约:将流中的元素反复结合起来就行运算,****得到一个值****。

​ T reduce(T identity,BinaryOption accumulator)

  • 归约分析

img

  • 实例

img

收集

  • 收集:用于给Stream中的元素进行汇总。
  • <R,A> R collect(Collect<? super T,A,R> collector)

方法形参:Collector接口

方法实参:应是Collector接口的实例;如何获取:有一个Collector类,里面提供了各种方法,返回给我们Collector接口实例。

  • 收集的应用场景

(1)将代码放入指定的集合

  • Collectors.toList()

img

  • Collectors.toSet()

img

  • Collectors.toMap()

​ 由于Map集合结构的特殊性,这里需要注意 ,与以上两个不同的是,需要指定存储的key和value.

img

(2)总数,平均值,总和,最大值,最小值(太过简单,不做过多描述)

img

img

(3)分组(简单)

img

(4)分区:满足条件的在一个分区,不满足条件的在另一个分区(注意:总共只划分出两个分区)

img

(5)连接:其实就是字符串拼接

img

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

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

相关文章

linux实验3编写内核模块,实验2.3_内核模块_实验报告

实验报告题目: 内核模块实验1、实验目的模块是Linux系统的一种特有机制&#xff0c;可用以动态扩展操作系统内核功能。编写实现某些特定功能的模块&#xff0c;将其作为内核的一部分在管态下运行。本实验通过内核模块编程在/porc文件系统中实现系统时钟的读操作接口。2、实验内…

Java 8 Stream Api 中的 peek、map、foreach区别

#1. 前言 我在Java8 Stream中讲述了 Java 8 Stream API 的一些内容。今天再看一下peek、map、foreach区别。 2. peek peek 操作接收的是一个 Consumer 函数。顾名思义 peek 操作会按照 Consumer 函数提供的逻辑去消费流中的每一个元素&#xff0c;同时有可能改变元素内部的一…

wapper打成linux服务,Wrapper配置详解及高级应用(转)

转自&#xff1a;http://286.iteye.com/blog/1921414将一个简单的程度如HelloWorld 的应用包装秤Wrapper 服务并不复杂&#xff0c;甚至可以认为非常简单。但是实际项目应用过程中我们的程序一般较庞大&#xff0c;运行环境也较复杂。通过Wrapper 配置文件的分析与配置进一步了…

Java8 Stream 流机制和 Lambda 表达式

一、Stream 流介绍与使用场景 Stream 流介绍 java8 中的stream 与InputStream和OutputStream是完全不同的概念, stream 是用于对集合迭代器的增强&#xff0c;使之完成能够完成更高效的聚合操作&#xff08;过滤、排序、统计分组&#xff09;或者大批量数据操作。stream 与 L…

linux guide编译器,GUIDE编译器-GUIDE编程工具-GUIDE编译器下载 v1.0.2官方版-完美下载...

GUIDE编译器是款跨平台的开发环境编程工具&#xff0c;支持C/C 和 Pascal三种语言&#xff0c;具有跨平台、操作简单、跨编程语言和单文件编译调试等特点&#xff0c;为用户提供单文件编译、调试和运行的环境。GUIDE编译器特色1、跨平台&#xff1a; GUIDE 可在 linux 平台和 w…

MySQL事务隔离级别和实现原理

经常提到数据库的事务&#xff0c;那你知道数据库还有事务隔离的说法吗&#xff0c;事务隔离还有隔离级别&#xff0c;那什么是事务隔离&#xff0c;隔离级别又是什么呢&#xff1f;本文就帮大家梳理一下。 MySQL 事务 本文所说的 MySQL 事务都是指在 InnoDB 引擎下&#xff0…

超级全面的MySQL优化面试解析

推荐阅读(点击即可跳转阅读) 1. SpringBoot内容聚合 2. 面试题内容聚合 3. 设计模式内容聚合 4. Mybatis内容聚合 5. 多线程内容聚合 超级全面的MySQL优化面试解析 本文概要 概述 为什么要优化 系统的吞吐量瓶颈往往出现在数据库的访问速度上随着应用程序的运行&#…

mysql linux导入csv主键,MySQL导入csv文件内容到Table及数据库的自增主键设置

写在前面目的是测试将csv文件内容导入到表中, 同时记录一下自增主键的设置.测试采用MySQL8.0.新建表customer_info如下, 未设置主键.修改上表, 添加主键id, 并设置为自增.ALTER TABLE customer_info ADD COLUMN id INT AUTO_INCREMENT NOT NULL PRIMARY KEY;导入步骤1.为了模拟…

mysql 优化方法有哪些?

MySQL索引 MySQL支持诸多存储引擎&#xff0c;而各种存储引擎对索引的支持也各不相同&#xff0c;因此MySQL数据库支持多种索引类型&#xff0c;如BTree索引&#xff0c;哈希索引&#xff0c;全文索引等等。为了避免混乱&#xff0c;本文将只关注于BTree索引&#xff0c;因为这…

Java基础面试题与答案

八种基本数据类型以及包装类 八种基本数据类型默认值&#xff1f;大小&#xff1f;范围区间&#xff1f;包装类的缓存区间&#xff1f; 序号类型名称默认值大小最小值最大值包装类缓冲区间1booleanfalse1B0(false)1(true)Boolean无2byte(byte)01B-128127Byte-128 ~ 1273char‘…

学习vim的linux游戏,PacVim:一个学习 vim 命令的命令行游戏 | Linux 中国

作者 | Sk 译者 | geekpi &#x1f48e; &#x1f48e; 共计翻译&#xff1a;735 篇 贡献时间&#xff1a;1691 天你好&#xff0c;Vim用户&#xff01;今天&#xff0c;我偶然发现了一个很酷的程序来提高 Vim 的使用技巧。Vim 是编写和编辑代码的绝佳编辑器。然而&#x…

Java多线程面试题与答案

线程 线程与进程的区别是什么&#xff1f; 进程指的是应用程序在操作系统中执行的副本&#xff08;系统分配资源的最小单位&#xff09;&#xff0c;线程是程序执行的最小单位&#xff1b;进程使用独立的数据空间&#xff0c;而线程共享进程的数据空间。 线程状态图 多线程会…

JVM面试题与答案

JVM内存布局 JVM在内存布局上可以分为哪些区域&#xff1f; 堆&#xff08;线程共享&#xff09;&#xff1a;GC的主要回收地&#xff0c;包含几乎所有的实例对象、字符串常量池&#xff1b;元空间&#xff08;线程共享&#xff09;&#xff1a;在本地内存分配&#xff0c;包…

md0和md1linux软raid,软RAID管理命令mdadm详解

mdadm是linux下用于创建和管理软件RAID的命令&#xff0c;是一个模式化命令。但由于现在服务器一般都带有RAID阵列卡&#xff0c;并且RAID阵列卡也很廉价&#xff0c;且由于软件RAID的自身缺陷(不能用作启动分区、使用CPU实现&#xff0c;降低CPU利用率)&#xff0c;因此在生产…

Dubbo常见面试题与答案

Dubbo的基础知识 Dubbo的核心架构是怎样的&#xff1f; Registry&#xff1a;注册中心。 负责服务地址的注册与查找&#xff0c;服务的 Provider 和 Consumer 只在启动时与注册中心交互。注册中心通过长连接感知 Provider 的存在&#xff0c;在 Provider 出现宕机的时候&#…

Redis常见面试题与答案

Redis的基本数据类型 Redis有哪些常用的数据类型&#xff1f; String&#xff1a;字符串&#xff08;最常用的缓存&#xff09;Hash&#xff1a;哈希&#xff08;保存对象&#xff09;List&#xff1a;有序列表&#xff08;消息队列&#xff09;Set&#xff1a;无序集合&…

c语言利用文件体写在桌面上,在C语言中怎样新建一个文件夹?

满意答案JacinthLancet推荐于 2017.10.12采纳率&#xff1a;56% 等级&#xff1a;12已帮助&#xff1a;35899人函数名: mkdir功 能: 建立一个目录(文件夹)用 法: int mkdir(char *pathname);程序例: (在win-tc和Dev-c下运行通过)#include #include #include int main(void){…

MySQL常见面试题与答案

存储引擎 InnoDB的主要特点是什么&#xff1f; MySQL5.5版本之后的默认存储引擎&#xff1b;支持事务&#xff1b;支持行级锁&#xff1b;支持MVCC&#xff1b;支持聚集索引方式存储数据。 InnoDB与MyISAM的区别&#xff1f; 存储引擎MyISAMInnoDB存储结构MyISAM在磁盘上存…

Spring 异常处理三种方式

Spring 异常处理三种方式 异常处理方式一. ExceptionHandler异常处理方式二. 实现HandlerExceptionResolver接口异常处理方式三. ControllerAdviceExceptionHandler三种方式比较说明(强烈推荐各位看一下&#xff0c;我觉得自己总结的比较多&#xff0c;嘿嘿&#xff0c;不对之…

Netty常见面试题 与 答案

Netty基础知识 什么是Netty&#xff1f; Netty 是一款用于高效开发网络应用的 NIO 网络框架&#xff0c;它大大简化了网络应用的开发过程&#xff1b; 封装了JDK底层的NIO模型&#xff0c;提供高度可用的API&#xff0c;用于快速开发高性能服务端和客户端&#xff1b;精心设计…