(原)

stream的内容比较多,先简单看一下它的说明:

A sequence of elements supporting sequential and parallel aggregate
* operations. The following example illustrates an aggregate operation using
* {@link Stream} and {@link IntStream}:
*
* <pre>{@code
* int sum = widgets.stream()
* .filter(w -> w.getColor() == RED)
* .mapToInt(w -> w.getWeight())
* .sum();
* }</pre>
* In this example, {@code widgets} is a {@code Collection<Widget>}. We create
* a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
* filter it to produce a stream containing only the red widgets, and then
* transform it into a stream of {@code int} values representing the weight of
* each red widget. Then this stream is summed to produce a total weight.

一个元素的序列,它支持一个串行和并行的聚合操作。下面的例子介绍了使用stream和intstream进行聚合操作。

这个例子里,widgets是一个集合,我们通过Collection.stream()创建了一个Widget的Stream对象。然后过滤了Color属性为RED的对象,然后将其转换成一个int值的Stream,它表示每个红色的重量,然后通过 sum将这些值累加起来。

通过文档能让我们大概的了解stream是怎样操作的。

* <p>In addition to {@code Stream}, which is a stream of object references,
* there are primitive specializations for {@link IntStream}, {@link LongStream},
* and {@link DoubleStream}, all of which are referred to as "streams" and
* conform to the characteristics and restrictions described here.

除了Stream之外(它是一种对象引用流),除此之外,还有一些针对于原生类型的聚化,例如IntStream、LongStream、DoubleStream,它们都被称作为“Stream”,并且它们都遵循这里所描述的stream的特性和限制。

* <p>To perform a computation, stream
* <a href="package-summary.html#StreamOps">operations</a> are composed into a
* <em>stream pipeline</em>. A stream pipeline consists of a source (which
* might be an array, a collection, a generator function, an I/O channel,
* etc), zero or more <em>intermediate operations</em> (which transform a
* stream into another stream, such as {@link Stream#filter(Predicate)}), and a
* <em>terminal operation</em> (which produces a result or side-effect, such
* as {@link Stream#count()} or {@link Stream#forEach(Consumer)}).
* Streams are lazy; computation on the source data is only performed when the
* terminal operation is initiated, and source elements are consumed only
* as needed.

通过Stream的计算,它的操作会将它组合到一个Stream管道中(Stream特别像Linux里面管道的概念),一个流的管道包含的源可能是一个数组、一个集合、一个函数或是IO channel,在Stream的计算中可能会包括一个或多个中间操作(这些中间操作会将这个Stream转换成另一个Stream,例如通过Stream#filter(Predicate)),和一个中止操作(它会产生一个结果,如Stream#count()),Stream是惰性和,它的源数据只有在终止操作初始化的时候才执行,源数据只有被需要的时候才会被消费。

上面的意思是说,比如。Stream.aaa().bbb().ccc().count();

aaa,bbb,ccc方法为Stream的中间操作。在最的一个count未被调用时,这些中间操作是不会被执行的,这意味这count是一个终止操作。

根据文档的描述,Stream的计算由三部分组中:

1、     源数据

2、     中间操作

3、     终止操作

这里的中间操作属于惰性求值,而终止操作属于及早求值。

那么Stream要怎样创建呢?

看这个方法:

/**
* Returns a sequential ordered stream whose elements are the specified values.
*
* @param <T> the type of stream elements
* @param values the elements of the new stream
* @return the new stream
*/
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

根据指定的元素返回一个有序有Stream

于是我们可以这样创建:

Stream stream1 = Stream.of("zhangsan", "lisi", "wangwu");

或者

String[] str2 = {"zhangsan", "lisi", "wangwu"};

Stream stream2 = Stream.of(str2);

或者通过List.stream()

List list3 = Arrays.asList("zhangsan", "lisi", "wangwu");

Stream stream3 = list3.stream();

我们通过IntStream创建流并将其输出:

IntStream.of(3,1,4,9).forEach(System.out::println);

在IntStream中有range和rangeClosed二个方法,接收二个参数,代表着一个整数区间范围,range表示不包含最后一位,rangeClosed表示包含最后一位。

IntStream.range(1,4).forEach(System.out::println);

System.out.println("---");

IntStream.rangeClosed(1,4).forEach(System.out::println);

如果现在有一个Int集合,要让集合里面的所有数值乘以2再相加得到最后的结果,用以前的写法不得不用循环的方式这么写:

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

Integer sum3 = 0;

for (Integer o : partList3) {

    sum3 += o * 2;

}

而通过Stream可以化成一行代码:

Integer sum33 = partList3.stream().map(integer -> integer * 2).reduce(0,Integer::sum);
/**
* Returns a stream consisting of the results of applying the given
* function to the elements of this stream.
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* @param <R> The element type of the new stream
* @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to apply to each element
* @return the new stream
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

这里的map方法接收一个Function参数,最后会返回一个Stream对象,记住,这里是一个中间操作。Map方法中的Function函数会传入一个参数,然后返回把这个参数经过处理后的结果,reduce方法是一个终止操作,将这些值都通过方法引用Integer::sum的方式加起来。其中reduce接收二个参数:

  T reduce(T identity, BinaryOperator<T> accumulator);

第一个参数可以认为是初始值,第二个参数是计算方式的函数,计算结果等价于:

T result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
}

如果将一个Stream对象转成一数组?

Stream<String> stream4 = Stream.of("a", "k", "g", "b");

Stream中有一个toArray方法。

/**
* Returns an array containing the elements of this stream, using the
* provided {@code generator} function to allocate the returned array, as
* well as any additional arrays that might be required for a partitioned
* execution or for resizing.
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
* @apiNote
* The generator function takes an integer, which is the size of the
* desired array, and produces an array of the desired size. This can be
* concisely expressed with an array constructor reference:
* <pre>{@code
* Person[] men = people.stream()
* .filter(p -> p.getGender() == MALE)
* .toArray(Person[]::new);
* }</pre>
*
* @param <A> the element type of the resulting array
* @param generator a function which produces a new array of the desired
* type and the provided length
* @return an array containing the elements in this stream
* @throws ArrayStoreException if the runtime type of the array returned
* from the array generator is not a supertype of the runtime type of every
* element in this stream
*/
<A> A[] toArray(IntFunction<A[]> generator)

这里除了使用之前说过的这种方式。

String[] streamArr1 = stream4.toArray(len -> new String[len]);

因为IntFunction这个函数接收一个Int类型为数组长度,返回一个数组的类型,我们也可以用文档中提供的例子这种方法。

String[] streamArr2 = stream4.toArray(String[]::new);

如果将一个Stream转换成List

Stream中提供了2个重载的方法

<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);

<R, A> R collect(Collector<? super T, A, R> collector);

下面一个方法可以看作是上面的缩写形式,

第一个方法中,文档中如此描述:

Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream. A mutable
* reduction is one in which the reduced value is a mutable result container,
* such as an {@code ArrayList}, and elements are incorporated by updating
* the state of the result rather than by replacing the result. This
* produces a result equivalent to:
* <pre>{@code
* R result = supplier.get();
* for (T element : this stream)
* accumulator.accept(result, element);
* return result;
* }</pre>

对这个流中的元素执行一个可变的汇聚的操作,一个可变的汇聚的操作指的是被汇聚的值是一个可变的结果容器,比如ArrayList, 这个集合是通过更新结果状态来合并的,而不是通过替换这个结果来合并的,这个结果等同于:

R result = supplier.get();
for (T element : this stream)
accumulator.accept(result, element);
return result;
}

参数1:Supplier,返回的对象是该方法返回的对象类型。

参数2:BiConsumer,接收的第一个参数可以理解是一个需要汇聚的对象,第二个参数是stream中的某一个元素。

参数3:BiConsumer,相当于是一个合并器,将上一次的结果和装进同一个对象中,用于最后的返回。当然这个对象的类型就是Supplier返回的对象类型。

例如这样:

Stream<String> stream5 = Stream.of("hello", "world", "good", "morning");

List<String> list5 = stream5.collect(() -> new ArrayList<>(),(list1,item) -> list1.add(item),(list2,list1) -> list2.addAll(list1));

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

这里有个简单的方法可以替代以上的代码

Stream<String> stream444 = Stream.of("list1", "list2", "list3");
List<String> list444 = stream444.collect(Collectors.toList());
list444.forEach(System.out::println);

Collectors中有很多方法,toList()只是将stream中的值存入ArrayList中返回。

如果想要换成LinkedList,可以用

Collectors.toCollection(LinkedList::new)

如果要将里面的值拼接成一个字符串返回,可以用

Collectors.joining()

在stream中,map作为一个映射方法,可以将集合中的无素作相处理,但如果集合中的每个元素都是一个list,要将这些list中的元素合并成一个集合,以前的做法就是用list.addAll()这个方法,现在可以利用stream中的另一个映射方法,floatMap.

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

它接收一个 Function函数,返回值为stream

于是可以这样写:

Stream<List<Integer>> stream7 = Stream.of(Arrays.asList(1,2), Arrays.asList(3), Arrays.asList(4,5));
List<Integer> list7 = stream7.flatMap(list -> list.stream()).collect(Collectors.toList());
System.out.println(list7);

将每个stream中的元素都展开,放在一个stream中,最后用collect方法放一个集合中输出。

 例子请看这里:https://github.com/LeeScofield/java8

Java 8 Stream介绍及使用1的更多相关文章

  1. Java 8 Stream介绍及使用2

    (原) stream中另一些比较常用的方法. 1. public static<T> Stream<T> generate(Supplier<T> s) 通过gen ...

  2. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...

  3. java之stream(jdk8)

    一.stream介绍 参考: Java 8 中的 Streams API 详解   Package java.util.stream   Java8初体验(二)Stream语法详解   二.例子 im ...

  4. Java笔记:Java 流(Stream)、文件(File)和IO

    更新时间:2018-1-7 12:27:21 更多请查看在线文集:http://android.52fhy.com/java/index.html java.io 包几乎包含了所有操作输入.输出需要的 ...

  5. Java 8 Stream

    1.关于Java8部分新特性介绍 Java8的新特性很多,在此就不一一介绍了,这里只说一下我自己在工作用用得比较多的几点: 1.1.Lambda表达式 Lambda允许把函数作为一个方法的参数(函数作 ...

  6. java.util.stream 库简介

    Java Stream简介 Java SE 8 中主要的新语言特性是拉姆达表达式.可以将拉姆达表达式想作一种匿名方法:像方法一样,拉姆达表达式具有带类型的参数.主体和返回类型.但真正的亮点不是拉姆达表 ...

  7. Java - 17 Java 流(Stream)、文件(File)和IO

    Java 流(Stream).文件(File)和IO Java.io包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io包中的流支持很多种格式,比如:基本类型. ...

  8. Java之Stream流

    Stream流的初步学习 初次学习Stream流的学习笔记,学习之前先了解一下函数式接口 概述 API是一个程序向使用者提供的一些方法,通过这些方法就能实现某些功能.所以对于流API来 说,重点是怎么 ...

  9. Java总结:Java 流(Stream)、文件(File)和IO

    更新时间:2018-1-7 12:27:21 更多请查看在线文集:http://android.52fhy.com/java/index.html java.io 包几乎包含了所有操作输入.输出需要的 ...

随机推荐

  1. oracle 简单备注

    1. 建立数据库 备注: 1) oracle 不同于mysql 可以直接create database 2) oracle 创建schema时对应一个用户,即该schema的访问用户,与用户一一对应: ...

  2. C#运算符的简单使用测试

    在代码中看到的代码中|=,有点不太理解故重新学习了下位运算符. 位运算符在 c# 中的测试用例 [TestMethod] public void TestMethod1() { var a = fal ...

  3. 百度APP移动端网络深度优化实践分享(二):网络连接优化篇

    本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<二>连接优化>,感谢原作者的无私分享. 一.前言 在<百度APP移动端网 ...

  4. Java核心技术第五章——2.Object类

    Object类:所有类的超类 Object类是Java中所有类的始祖,在Java中每个类都是由它扩展而来的.但是并不需要这样写: public class Emloyee extends Object ...

  5. 从壹开始前后端分离 [ Vue2.0+.NetCore2.1] 二十六║Client渲染、Server渲染知多少{补充}

    前言 书接上文,昨天简单的说到了 SSR 服务端渲染的相关内容<二十五║初探SSR服务端渲染>,主要说明了相关概念,以及为什么使用等,昨天的一个小栗子因为时间问题,没有好好的给大家铺开来讲 ...

  6. Docker 删除&清理镜像

    文章首发自个人网站:https://www.exception.site/docker/docker-delete-image 本文中,您将学习 Docker 如何删除及清理镜像? 一.通过标签删除镜 ...

  7. 写给 Android 开发的小程序布局指南,Flex 布局!

    一.序 Hi,大家好,我是承香墨影! 最近在做小程序,验证一些方向,开发效率确实很快,就是各种微信的审核有点费劲,但是总归是有办法解决的. 想要开发一款小程序,其实和我们正常写一款 App 类似,你需 ...

  8. Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

    前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...

  9. 简说Java线程的那几个启动方式

    本文首发于本博客 猫叔的博客,转载请申明出处 前言 并发是一件很美妙的事情,线程的调度与使用会让你除了业务代码外,有新的世界观,无论你是否参与但是这对于你未来的成长帮助很大. 所以,让我们来好好看看在 ...

  10. SpringMVC+Spring+Mybatis整合

    SpringMVC+Spring+Mybatis整合 导包 配置jdbc.properties.log4j.properties jdbc.driver=com.mysql.jdbc.Driver j ...