java 8 之Streams 解说

java 8 之Streams 解说

基本概念

java 8新增的集合streams操作,简化了我们显示的遍历集合操作行为,而且提供内置的并发功能

Streams操作中,如果操作产生的结果还是stream是lazy operation,但结果如果是void或者其他的value值则是eager operation,lazy operation做的目的是为了操作效率

Streams的 api 中lazy operation类似我们常见的 建造者模式(Builder Pattern),以前我们是设置类的属性,这里我们设置的是行为。

代码示例:

package com.doctor.stream;

import java.util.List;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;

/**
 * @author sdcuike
 *
 *         Created on 2016年6月10日 下午4:29:32
 *
 *         It’s very easy to figure out whether an operation is eager or lazy: look at what it returns.
 *         If it gives you back a Stream, it’s lazy; if it gives you back another value or void, then it’s
 *         eager. This makes sense because the preferred way of using these methods is to form a
 *         sequence of lazy operations chained together and then to have a single eager operation
 *         at the end that generates your result.
 *
 *         This whole approach is somewhat similar to the familiar builder pattern. In the builder
 *         pattern, there are a sequence of calls that set up properties or configuration, followed
 *         by a single call to a build method. The object being created isn’t created until the call
 *         to build occurs
 *
 *         I’m sure you’re asking, “Why would we want to have the differentiator between lazy and
 *         eager options?” By waiting until we know more about what result and operations are
 *         needed, we can perform the computations more efficiently.
 */
public class StreamDemo {

    public static void main(String[] args) {
        List<String> names = Lists.newArrayList("doctor", "lily", "who", "doctor who");
        List<String> result = names.stream().filter(e -> {
            System.out.println("filter 1 :" + e);
            return e.startsWith("do");
        }).filter(e -> {
            System.out.println("filter 2 :" + e);
            return e.startsWith("doctor");
        }).collect(Collectors.toList());

        System.out.println("result:" + result);
    }

}

执行结果:

filter 1 :doctor
filter 2 :doctor
filter 1 :lily
filter 1 :who
filter 1 :doctor who
filter 2 :doctor who
result:[doctor, doctor who]

由执行的结果,我们可以看出,Streams的filter操作是lazy operation,而collect操作是eager operation。

基本操作

1.collect(toList())

此操作是eager operation,从流中产生某种类型的数值列表。

 List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());
        boolean equals = Arrays.asList("a", "b", "c").equals(list);
        Preconditions.checkState(equals); // true

2.map

我们经常需要将数据从一种形式转换到另一种形式的操作函数,而map操作就可以对流中的数据应用此函数,从而产生包含新值的数据流。

List<String> mapOperation = Stream.of("a", "b", "doctor who").map(String::toUpperCase).collect(Collectors.toList());
        Preconditions.checkState(Arrays.asList("A", "B", "DOCTOR WHO").equals(mapOperation));

3.filter

可参考前面的代码例子。主要和以前我们写的if条件判断功能一样,过滤数据流中的数据功能。

4.flatMap

map操作,我们之前也看到了,它将流中的数据从一个类型转换到其他类型(非流类型),但如果我们将流中的数据转变成了流该如何操作,这时候我们就用到了  flatMap  操作,它会将产生的流合并成一个流继续下面的操作。

  // flatMap lets you replace a value with a Stream and concatenates all the streams together.
        List<Integer> flatMapOperation = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4)).flatMap(e -> e.stream()).collect(Collectors.toList());
        Preconditions.checkState(Arrays.asList(1, 2, 3, 4).equals(flatMapOperation));

5.max and min

这个操作很容易理解,就是找出列表数据中的最大值和最小值。

   Integer max = Stream.of(1, 2, 66).max(Integer::compareTo).get();
        Preconditions.checkState(max.equals(66));

6.reduce

当你想要对集合中的数据处理后得到唯一的结果时,我们借助  reduce操作。

 int intValue = Stream.of(1, 2, 3).reduce(0, (acc, e) -> acc + e).intValue();
        Preconditions.checkState(intValue == 6);

看一下java doc的说明:

Open Declaration Integer java.util.stream.Stream.reduce(Integer identity, BinaryOperator<Integer> accumulator)

Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. This is equivalent to: 

T result = identity;
     for (T element : this stream)
         result = accumulator.apply(result, element)
     return result;
but is not constrained to execute sequentially.
The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t. The accumulator function must be an associative function. 

This is a terminal operation.

Parameters:
identity the identity value for the accumulating function
accumulator an associative, non-interfering, stateless function for combining two values
Returns:
the result of the reduction
@apiNote
Sum, min, max, average, and string concatenation are all special cases of reduction. Summing a stream of numbers can be expressed as:
Integer sum = integers.reduce(0, (a, b) -> a+b);
or:
Integer sum = integers.reduce(0, Integer::sum);
While this may seem a more roundabout way to perform an aggregation compared to simply mutating a running total in a loop, reduction operations parallelize more gracefully, without needing additional synchronization and with greatly reduced risk of data races.

时间: 2024-10-11 05:40:54

java 8 之Streams 解说的相关文章

Java基础——JSP

一.JSP的由来 在很多动态网页中,绝大多部分内容是不变的,只有局部内容需要动态产生和改变.例如, 一个新闻的浏览次数,只有这个次数是动态改变的,而Servlet程序返回客户端的代码全是java程序动态创建的.Servlet 的缺点,处理界面困难.JSP 是在Servlet的基础上发展起来的,它弥补了Servlet在界面处理方面的缺陷. 简单来讲,JSP =html+java片段+jsp标签+javascript,它功能强大,可以和javabean 结合 另外,JSP+javabeen+serv

Java循环删除集合多个元素的正确打开方式

首先说下不正确的打开方式: 第一:使用for循环删除集合的元素,示例代码如下 1 ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); 2 for (int i = 0; i < list.size(); i++) { 3 list.remove(i); 4 } 5 System.out

使用Spring data Jpa 时遇到 java.lang.ClassNotFoundException: org.springframework.core.ReactiveTypeDescriptor

背景 原本项目是使用SSM+Maven进行开发,而后想同时使用Jpa(即mybatis和jpa混用),配置好相关文件后,使用Junit做测试时,出现以下错误. 主要: ERROR - Caught exception while allowing TestExecutionListener [org.springframewor[email protected]29774679] to prepare test instance [[email protected]]java.lang.Ille

和朱晔一起复习Java并发(一):线程池

和我之前的Spring系列文章一样,我们会以做一些Demo做实验的方式来复习一些知识点. 本文我们先从Java并发中最最常用的线程池开始. 从一个线程池实验开始 首先我们写一个方法来每秒一次定时输出线程池的基本信息: private void printStats(ThreadPoolExecutor threadPool){ Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { log.info("

Oracle Instance

文章为学习汇总网上资料 instance = 内存结构(SGA,system global area) +后台进程 内存结构 = 共享池+数据高速缓存+重做日志缓冲区+其他 后台进程 = DBWn(database writer n个)+LGWR(log writers)+SMON(system monniter)+PMON(progress moniter)+CKPT(checkpoint)+-- PGA(Program Global Area)= 服务器进程+后台进程 下面分别介绍各部分:

编写难于测试的代码的5种方式

本文由码农网 – 孙腾浩原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 有一次,我在一个讲座上听到主持人问听众如何故意编写难于测试的代码.在场的小伙伴都惊呆了,因为没有任何人会故意写这种糟糕的代码.我记得他们甚至给不出一个好的答案. 当然,这个问题的目的不在于教大家如何写使同事欲哭无泪的烂代码.而是为了了解什么样的代码难于测试,来避免这些严重的问题. 这里给出我对上面那个问题的答案(当然这只是我的个人观点,每个人讨厌的都不尽相同.) 1.用大量的静态字段 尤其是在不同类中共享静

oracle体系结构详解

Oracle体系结构就是围绕这张图展开的,要想深入了解oracle,就必须把这张图搞明白. 如图: 一.基本组成: Oracle server: 一般情况下是一个instance和一个database组成 1个instance只能对应一个数据库.    特殊:1个数据库可以有多个instance(rac) 一台服务器上同时可装多套版本的数据库软件,每个数据库软件可建多个数据库,但是每个数据库只对应一个instance,也可以理解成每个数据库只有一个SID . 利用DBCA建出的每个库都是相对独立

ORA-4031错误 解决方法

遇到ORA-4031错误时,你的心里会不会发怵?ORA-4031很容易导致数据库出现异常崩溃,当Oracle的核心进程无法获得共享池内存时,它们会把数据库异常宕掉.当然,ORA-4031就像黄灯一样,它在提醒你需要马上采取紧急策略了.不是说它一出现,数据库马上就会宕机. 话题讨论: 1.ORA-4031是Oracle中最令人厌恶的报错,它的出现有哪几种原因? 2.一旦出现4031错误,也就是说共享池内存不足的情况下,我们该如何释放内存呢?你有木有遇到过相应的情形呢?请回忆下当时是如何解决的? 3

Oracle内存管理(之五)

[深入解析--eygle]学习笔记 1.4. 2其他内存组件 Large Pool-大池是SGA的一个可选组件,通常用于共享服务器模式(MTS). 并行计算或 RMAN的备份恢复等操作. Java Pool-Java池主要用于JVM等Java选件. Streams Pool-Streams pool是Oracle10g引入的概念,为Oracle的Streams功能所使用,如果不定义该参数,这部分内存将从Shread Pool中分配 对于SGA各部分内存分配,可以从数据库的视图中查询得到: 17: