• 流接口--BaseStream接口

流API定义了几个流接口,这些接口包含在java.util.stream中。BaseStream是基础接口,它定义了所有流都可以使用的基本功能。我们来看一下源码:

public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable {}

这是一个泛型接口,T指定流中元素的类型,S指定扩展BaseStream的流的类型。BaseStream类extends了AutoCloseable接口,所以可以使用带资源的try语句管理流。在大多数的情况下,比如数据源是集合的时候,都不需要关闭流的。

这个类基本实际编码中基本不会用到,里面的几个方法也都是些属性状态判断的方法,所以了解下就好了,这里不列出具体的API了。我们还要主要研究下Stream接口,几个基本类型的接口我们最后整理。





  • 流接口--Stream接口

Stream也是一个接口,ReferencePipeline是它具体的实现类。具体的实现类,我们不用关心,因为一般都是直接使用这个接口的API就好了。Stream接口的定义如下:

public interface Stream<T> extends BaseStream<T, Stream<T>> {}

这个类里面好多方法我们要认真的了解下的,我们学习流API其实也就是学习这几个方法而已,在详细的整理的API之前,先来说3组概念。

  • 1,终端操作VS中间操作

终端操作会消费流,这种操作作用于产生结果,例如找出流中最小的值,或者执行某种操作,比如forEach方法。一个流被消费后,就不能被重用了。

中间操作会产生另外一个流,所以,中间操作可以用来创建执行一系列动作的管道。

  • 2,延迟行为

延迟机制就是说某一种操作不是立即发生的。可能在中间的某一个时刻才会发生。上面的中间操作就不是立即发生的。当在中间操作创建的新流上执行终端操作后,中间操作指定的操作才会发生。之所有有这种机制,应该是出于性能原因吧,延迟行为可以让流API更加高效的执行

  • 3,有状态VS无状态

无状态操作就是说,独立于其他元素来处理每一个元素。在有状态的操作中,每个元素的处理可能依赖于其他的元素。举个例子吧:比如说排序就应该是有状态操作,因为元素的顺序依赖于其他的元素的值。比如说过滤就应该是无状态操作,因为每个元素都是被单独处理的。当需要并行处理流的时候,无状态和有状态的区别最为重要,因为有状态操作可能需要多次处理才能完成。





其实学习流API挺简单的,就是获取一个流,然后调相关的流API来操作就OK了。

  • 1,如何获取流?

想要获取一个流,肯定要有一个数据源,这是实际编码中最常见的情景。

1),如果数据源是集合的话,有2个方法可以获得一个流,下面是Collections的2个获取流的源码:

//该方法默认返回一个顺序流
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
} //该方法默认返回一个并行流,如果无法获得一个并行流,也有可能返回一个顺序流
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}

2),如果数据源是数组的话,用Arrays工具类的一个stream()静态方法,

public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}

该方法还有几个重载方法,用来返回处理基本类型的数组,他们返回的类型有IntStream,DoubleStream,LongStream。

3),通过对一个流做中间操作来获取一个新的流。

4),创建包含指定元素集合的流,使用of()方法。如果想要创建一个不包含任何元素的Stream,可以使用Stream的静态方法empty()。

5),通过创建无限Stream的静态方法,generate()方法,iterate()方法





关于获取流,下面整理一段演示代码:

/**
* @创建作者: LinkinPark
* @创建时间: 2015年11月3日
* @功能描述: 获取流
*/
public class Test
{ public static void main(String[] args)
{
//1,数据源是集合,从集合中获取一个流
List<Integer> list = new ArrayList<>(3);
list.add(1);
list.add(2);
list.add(3);
Stream<Integer> stream1 = list.stream(); //2,数据源是一个数组,从数组中获取一个流
Integer[] array = list.toArray(new Integer[0]);
Stream<Integer> stream2 = Arrays.stream(array); //3,使用原来的一个流来生成一个新的流
Stream<Integer> stream3 = stream1.filter((i) -> true); //4,直接使用Stream接口的静态方法of
Stream<Integer> stream4 = Stream.of(1, 2, 3);
stream4.forEach(System.out::println); //Stream的静态方法empty()
Stream<String> emptyStream = Stream.empty();
//上面的这行代码会被编译器推导出来,和下面这行代码效果一样
Stream<String> emptyStream1 = Stream.<String> empty(); //5,Stream接口有2个静态方法,可以创建无限Stream
Stream<String> generate = Stream.generate(() -> "LinkinPark...");
Stream<Double> generate2 = Stream.generate(Math::random);
generate2.forEach(System.out::println);
Stream<BigInteger> iterate = Stream.iterate(BigInteger.ZERO, n->n.add(BigInteger.ONE));
} }
  • 2,OK,现在我来整理下具体的流的API:

先来整理中间操作的方法:

filter(),过滤掉Steam中所有不符合predicate接口的元素

mapToXxx(),对流中的元素执行一对一的转换,该方法返回的新流中包含了ToXxxFunction接口的元素

peek(),依次对每个元素执行一些操作,该方法返回的流与原来流包含相同的元素,该方法主要用于调试。

distinct(),排序流中所有重复的元素,注意,这里元素重复的标准是使用equals()返回true。该方法有状态

sorted(),保证流中的元素在后续的访问中出于有序状态。该方法有状态

limit(),用于保证对流的后续访问中最大允许访问的元素个数。该方法有状态





整理几个终端操作的方法:

forEach(),遍历流中的所有元素,对每个元素执行Consumer接口

toArray(),将流中所有的元素转换成一个数组

reduce(),用于通过某种操作来合并流中的元素

min(),返回流中所有元素的最小值

max(),返回流中所有元素的最大值

count(),返回流中所有元素的数量

anyMatch(),判断流中是否至少包含一个元素符合Predicate接口

allMatch(),判断流中是否每个元素都符合Predicate接口

noneMatch(),判断流中是否所有元素都不符合Predicate接口

findFirst(),返回流中的第一个元素

findAny(),返回流中的任意一个元素

  • 3,一个简单的流示例

OK,现在通过一段代码来做一个简单的流示例:

public static void main(String[] args) throws Exception
{
//这里初始化一个list,下面Stream所有的操作都不会影响这个数据源的
List<Integer> list = new ArrayList<>(3);
list.add(1);
list.add(2);
list.add(3);
//获取一个流,来演示下min取最小值的操作
Stream<Integer> stream = list.stream();
Optional<Integer> min = stream.min(Integer::compare);
min.ifPresent(System.out::println);
//上面的min是终端操作,所以流被消费了。下面演示下链式操作,这也是Optional类和Stream流推荐的方式
list.stream().filter((value) -> value < 2).forEach(System.out::println);
list.stream().max(Integer::compare).filter((value) -> value > 5).orElseThrow(() -> new Exception("这里随便一个异常"));
}



流API--流的基础知识的更多相关文章

  1. 响应式流API的构建基础

    下面三个重要的概念是响应式流API的构建基础: 发布者是事件的发送方,可以向它订阅. 订阅者是事件订阅方. 订阅将发布者和订阅者联系起来,使订阅者可以向发布者发送信号. http://www.info ...

  2. 关于Java中面向对象章节、IO 流中的重点基础知识。

    一.面向对象的三大特征,以及作用. 答:面向对象的三大特征即,封装性.继承性.多态性. 其分别的作用为 : 封装作用:将数据封装起来,提高数据的安全性, 继承作用:提高代码的复用性,减少冗余代码. 多 ...

  3. Redis基础知识补充及持久化、备份介绍(二)--技术流ken

    Redis知识补充 在上一篇博客<Redis基础认识及常用命令使用(一)--技术流ken>中已经介绍了redis的一些基础知识,以及常用命令的使用,本篇博客将补充一些基础知识以及redis ...

  4. 乐字节Java之file、IO流基础知识和操作步骤

    嗨喽,小乐又来了,今天要给大家送上的技术文章是Java重点知识-IO流. 先来看看IO流的思维导图吧. 一. File 在Java中,Everything is Object!所以在文件中,也不例外! ...

  5. C# 基础知识系列- 14 IO篇 流的使用

    0. 前言 继续之前的C# IO流,在前几篇小短片中我们大概看了下C# 的基础IO也对文件.目录和路径的操作有了一定的了解.这一篇开始,给大家演示一下流的各种操作.以文件流为例,一起来看看如何操作吧. ...

  6. Java基础知识回顾之六 ----- IO流

    前言 在上一篇文章中,回顾了Java的多线程.而在本篇文章中主要介绍Java IO的相关知识. IO的介绍 什么是IO? IO的名称又来是Input与Output的缩写,也就是输入流和输出流.输入流用 ...

  7. JAVA基础知识之IO——IO流(Stream)的概念

    Java IO 流 Java将不同的设备或载体(键盘.文件.网络.管道等)的输入输出数据统称为"流"(Stream),即JAVA的IO都是基于流的. JAVA传统的所有流类型类都包 ...

  8. Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)

    1. 使用字符流缓冲流的特殊功能 [ newLine() / readLine() ] 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中  数据源: a.txt -- 读取数据 ...

  9. Java基础知识强化之IO流笔记39:字符流缓冲流之复制文本文件案例01

    1. 字符流缓冲流之复制文本文件案例 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 数据源: a.txt -- 读取数据 -- 字符转换流 -- InputStreamRe ...

随机推荐

  1. (译)Web是如何工作的(3):HTTP&REST

    原文地址:https://medium.freecodecamp.org/how-the-web-works-part-iii-http-rest-e61bc50fa0a   我们在第一篇文章中介绍了 ...

  2. PE文件详解二

    本文转自小甲鱼的PE文件相关教程,原文传送门 咱接着往下讲解IMAGE_OPTIONAL_HEADER32 结构定义即各个属性的作用! 接着我们来谈谈 IMAGE_OPTIONAL_HEADER 结构 ...

  3. MySQL的insert ignore与replace into不同

    以前从来没有接触过replace into这个语法,但是却看到很多人都在使用这个语法,并且应用在很多生产环境中,于是我也去学习了一下repalce into的用法. 关于replace 一句话:正常情 ...

  4. flask动态url规则

    动态URL规则 URL规则可以添加变量部分,也就是件更符合同规则的URL抽象成一个URL模式. @app.route('/item/<id>') def item(id): return ...

  5. Nginx常用配置实例(4)

    Nginx作为一个HTTP服务器,在功能实现方面和性能方面都表现得非常卓越,完全可以与Apache相媲美,几乎可以实现Apache的所有功能,下面就介绍一些Nginx常用的配置实例,具体包含虚拟主机配 ...

  6. HTML基础知识(表格、表单)

    6.表格 l  概念:表格一定具有行和列 注:使用<thead><tbody><tfoot>,使浏览器能独立于表格表头和表格页脚的表格主体滚动.当包含多个页面的表格 ...

  7. 有关java里,nextLine()无法输入的问题

    在课后习题中用到了以下代码 public static void main(String[] args) { System.out.print("输入学生人数:"); int st ...

  8. 列表(List) 的增删改查及其他方法 和元组(tuple)的查

    一.列表 1.列表简介: 列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,他是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如:li ...

  9. 循序渐进之Spring AOP(1) - 原理

    AOP全称是Aspect Oriented Programing,通常译为面向切面编程.利用AOP可以对面向对象编程做很好的补充. 用生活中的改装车比喻,工厂用面向对象的方法制造好汽车后,车主往往有些 ...

  10. sass 安装与使用

    1.安装. 安装ruby :http://rubyinstaller.org/downloads 创建项目:在f盘创建一个名为sass的文件夹 ruby命令行:f: ruby命令行:cd sass r ...