Stream

Stream 是用函数式编程方式在集合类上进行复杂操作的工具。

一)常用的流操作

惰性求值方法:只描述Stream,最终不产生新集合的方法(返回的还是Stream)。

及早求值方法:最终会从Stream产生值的方法。

1.创建Stream:

java.util.Collection<E> 

default Stream<E> stream()

default Stream<E> paralleStream()

产生当前集合中所有元素的流,paralleStream()以并行的方式产生。

java.util.stream.Stream 

static <T> Steam<T> of(T...values)

产生一个元素为给定值的流

static <T> Stream<T> empty()

产生一个不包含任何元素的流

static <T> Stream<T> generate(Supplier<T> s)

产生一个无限流,它的值是通过反复调用函数s而构建的

static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

产生一个无限流,它的元素包含种子、在种子上调用f产生的值,在前一个元素上调用f产生的值

java.util.Arrays

static <T> Stream<T> stream(T[] array, int off, int len)

产生一个流,它的元素是由数组中指定范围内的元素构成。

java.util.regex.Pattern 

Stream<String> splitAsStream(CharSequence input)

产生一个流,它的元素是输入中该模式界定的部分。

java.nio.file.Files     

static Stream<String> lines(Path path)

static Stream<String> lines(Path path, Charset cs)

获取值产生一个流,它的元素是指定文件中的行,该文件的字符集为UTF-8,或者为指定的字符集。

java.util.function.Supplier<T> T get()

 2 //该方法接受可变长度的参数
3 Stream<String> s=Stream.of("tang","jia","jiu");
7
8 Stream.generate(Supplier<T> s);
9 Stream<String> echos=Stream.generate(() -> "Echo");
Stream<Double> random = Stream.generate(Math::random);
Stream<String> pattern = Pattern.compile("\\|").splitAsStream(str);
10 //如果要创建一个行如0 1 2 3.......的无限序列可使用: 
12 Stream<BigInteger> integers=Stream.iterate(BigInteger.ZERO,n -> n.add(BigInteger.ONE));

2.转换Steam

java.util.stream.Stream

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

转换一个流中的值,并产生一个新的流。

1 List<String> collected = Stream.of("a", "b", "hello")
2 .map(string -> string.toUpperCase()) //Lambda 表达式必须是 Function 接口的一实例
3 .collect(toList());
4 assertEquals(asList("A", "B", "HELLO"), collected);

Stream<T> filter(Predicate<? super T> predicate)

产生一个新的流,包含符合某种条件的所有元素。

1 List<String> beginningWithNumbers
2 = Stream.of("a", "1abc", "abc1")
3 .filter(value -> isDigit(value.charAt(0))) //必须是Predicate
4 .collect(toList());

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

flatMap 方法可用 Stream 替换值, 然后将多个 Stream 连接成一个 Stream

1 List<Integer> together = Stream.of(asList(1, 2), asList(3, 4))
2 .flatMap(numbers -> numbers.stream()) //必须是Function
3 .collect(toList());
4 assertEquals(asList(1, 2, 3, 4), together);

Stream<T> limit(long n)

返回一个包含前n个元素的新流。

Stream<T> skip(int n)

与之相反会丢弃掉前面的n个元素,返回新流。

static <T> Stream<T> contact(Stream<? extends T> a, Stream<? extends T> b)

拼接a和b两个流

Stream<T> distinct()

产生一个抑制了相同元素的新流。

Stream<T> sorted()

Stream<T> sorted(Comparator<? super T> comparator)

产生一个流,它的元素是当前流中所有元素按顺序排列的,第一个方法要求元素是

实现了Comparable的类的实例。

Stream<T> peek(Consumer<? super T> action)

产生一个流,它的元素与流中的元素相同,但在每次获取一个元素时,都会调用一个函数,这对调试来说非常方便。

3.得到值

java.util.stream.Stream 

Optional<T> max(Comparator<? super T> compartor)

Optional<T> min(Comparator<? super T> compartor)

分别得到这个流的最大元素和最小元素

Optional<T> findFirst()

Optional<T> findAny()

分别得到这个流的第一个和任意一个元素

boolean anyMatch(Predicate<? super T> predicate)

boolean allMatch(Predicate<? super T> predicate)

boolean noneMatch(Predicate<? super T> predicate)

分别在这个流中任意元素、所有元素和没有元素匹配给定断言时返回true。

这些操作都是终结操作。

4.Optional类型

Optional<T>是一种包装器对象,要么包装了类型T的对象,要么没有包装任何对象。

有效使用Optional的关键:它在值不存在的情况下会产生一个可替代物,而只有在值

存在的情况下才会使用这个值。

在没有任何匹配时,使用默认值:

String result = optionalStr.orElse("");
String result = optionalStr.orElseGet(() -> Locale.getDefault().getDisplayName());
String result = optionalStr.orElseThrow(IllegalStateException::new)

值存在是使用值:

optionalValue.ifPresent(v -> Process V);
optionalValue.ifPresent(v -> result.add(v));
//注意调用ifPresent不会返回任何值,如果想要结果可使用map
optionValue.map(results::add);

java.util.Optional 

T orElse(T other)

获取Optional的值,或者在Optional为空时,产生other

T orElseGet(Supplier<? extends T> other)

获取Optional的值,或者在Optional为空时,获取调用other产生的结果

<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

获取Optional的值,或者在Optional为空时,抛出异常。

void ifPresent(Consumer<? super T> consumer)

如果该Optional不为空,那么就将它的值传递给consumer

<U> Optional<U> map(Function<? super T, ? extneds U> mapper)

获取将该Optional值传递给mapper后的结果,只要这个Optional的结果不为

空且结果不为null,否则产生一个空Optional。

不适合使用Optional值的方式: 

Optional<T> optionalValue = ...;
optionalValue.get().someMethod();
//并不比下面的方式安全:
T value = ...;
value.someMethod();
if (optionalValue.isPresent()) optionalValue.get().someMethod()
//并不比下面的方式简单:
if (value != null) value.someMethod();

java.util.Optional 

T get()

获取Optional的值,或者在该Optional为空时,抛出NoSuchElementException。

boolean isPresent()

如果Optional不为空时,返回true。

static <T> Optional<T> of(T value)

static <T> Optional<T> ofNullable(T value)

产生一个具有给定值的Optional。如果value为null,那么第一个方法会抛出

NullPointerException对象,而第二个方法会产生一个空Optional.

static <T> Optional<T> empty()

产生一个空Optional。

<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

产生将mapper应用于当前Optional值所产生的结果,或者在当前Optional为空时,返回一个空Optional

5.收集器

java.util.stream.BaseStream 

Iterator<T> iterator()

产生一个用于获取当前流中各个元素的迭代器。

java.util.stream.Stream

void forEach(Consumer<? super T> action)

在流的每个元素上调用action,这是一个终结操作,会以任意顺序遍历各个元素。

Object[] toArray()

<A> A[] toArray(IntFunction<A[]> generator)

产生一个数组对象,或者在将引用A[]::new传递给构造器时,返回一个A类型的数组。

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

使用给定的收集器来收集当前流中的元素,Collectors类中有多种收集器的工厂方法。

java.util.stream.Collectors 

static <T> Collector<T,?,List<T>> toList()

static <T> Collector<T,?,Set<T>> toSet()

产生一个收集器

static <T,C extends Collection<T>> Collector<T,?,C> toCollection(Supplier<C> collectionFactory)

产生一个将元素收集到任意集合中的收集器。可以传递一个诸如TreeSet::new的构造器引用。

static Collector<CharSequence,?,String> joining()

static Collector<CharSequence,?,String> joining(CharSequence delimiter)

static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

产生一个链接字符串的收集器,分隔符会置于字符串之间,而第一个字符串可之前可以有前缀,最后一个字符串之后可以有后缀。

static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFuntion<? super T> mapper)

static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFuntion<? super T> mapper)

static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFuntion<? super T> mapper)

产生对应的SummaryStatistics收集器,通过它可以进行各自计算

IntSummaryStatistics

LongSummaryStatistics

DoubleSummaryStatistics 

long getCount()

(int|long|double) getSum()

double getAverage()

(int|long|double) getMax()

(int|long|double) getMin()

收集到map中:

Map<Integer, String> idToName = users.stream().collect(Collectors.toMap
(User::getUserId, User::getName));
Map<Integer, User> userMap = users.stream().collect(Collectors
.toMap(User::getUserId, Function.identity()));

java.util.stream.Collector

static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T, ? extends K> key, Function<? super T, ? extends U> value) 

key:产生Map的键  value:产生Map的值

static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T, ? extends K> key,

Function<? super T, ? extends U> value,BinaryOperator<U> mergeFunction)

如果多个元素具有相同的键就会存在冲突,收集器会抛异常。mergeFunction函数引元来覆盖这种行为,

该函数会针对给定的已有值和新值来解决冲突并确定键对应的值。这个函数该返回已有值,新值或者它们的组合。

static <T,K,U,M> Collector<T,?,M> toMap(Function<? super T, ? extends K> key,

Function<? super T, ? extends U> value,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier)

mapSupplier:例如TreeMap::new

群组和分区:

java.util.stream.Collectors 

static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)

返回一个收集器,它会产生一个映射表,其键是将classifier应用于所有收集到的元素上产生的结果,

而值是由具有相同键的元素构成的一个个列表。

static <T, K> Collector<T, ?, Map<Boolean, List<T>> partitioningBy(Predicate<? super T> predicate)

产生一个收集器,它会产生一个映射表,其键是ture或者false,而值是由满足或者不满足断言的元素构成的列表。

6.下游收集器

groupingBy()方法会产生一个Map,它的每个值都是一个List。如果想要以某种方式来处理这些List,

就需要提供一个下游收集器。例如,如果想要获得Set而不是列表,那么可以使用Collector.toSet:

java.util.stream.Collectors 

static <T> Collector<T,?,Long> counting()

产生一个可以对收集到的元素进行计数的收集器。

static <T> Collector<T,?,Integer> summingInt(ToIntFunction<? super T> mapper)

求和

此外还有maxBy,minBy,mapping

7.聚合操作

一般来说,如果聚合方法有一个聚合操作op,那么该操作会产生v0 op v1 op v2......,其中 vop vi+1就表示我们编写的函数调用op(vi,vi+1).

该操作应该是联合的,即与你组合元素的顺序无关。

1 Stream<Integer> values=.....;
2 Optional<Integer> sum=values.reduce((x,y) -> x+y);

通常,如果有一个标识e使得e op x=x,那么你就可以使用该元素作为计算的起点。

Optional<Integer> sum=values.reduce(0,(x,y) -> x+y);

当流为空时会返回标识值。

假设现在你有包含多个对象的流,并且希望对它的某个属性求和。

int result=words.reduce(0,
(total,word) -> total+word.length(),
(total1,total2) -> total1+total2);

Java8新特性----Stream的更多相关文章

  1. Java8 新特性 Stream 非短路终端操作

    非短路终端操作 Java8 新特性 Stream 练习实例 非短路终端操作,就是所有的元素都遍厉完,直到最后才结束.用来收集成自己想要的数据. 方法有: 遍厉 forEach 归约 reduce 最大 ...

  2. Java8 新特性 Stream 短路终端操作

    短路终端操作 Java8 新特性 Stream 练习实例 传入一个谓词,返回传为boolean,如果符合条件,则直接结束流. 匹配所有 allMatch 任意匹配 anymMatch 不匹配 none ...

  3. Java8 新特性 Stream 无状态中间操作

    无状态中间操作 Java8 新特性 Stream 练习实例 中间无状态操作,可以在单个对单个的数据进行处理.比如:filter(过滤)一个元素的时候,也可以判断,比如map(映射)... 过滤 fil ...

  4. Java8 新特性 Stream() API

    新特性里面为什么要加入流Steam() 集合是Java中使用最多的API,几乎每一个Java程序都会制造和处理集合.集合对于很多程序都是必须的,但是如果一个集合进行,分组,排序,筛选,过滤...这些操 ...

  5. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

  6. java8新特性--Stream的基本介绍和使用

    什么是Stream? Stream是一个来自数据源的元素队列并可以进行聚合操作. 数据源:流的来源. 可以是集合,数组,I/O channel, 产生器generator 等 聚合操作:类似SQL语句 ...

  7. Java8新特性Stream流应用示例

    Java8新特性介绍 过滤集合 List<String> newList = list.stream().filter(item -> item != null).collect(C ...

  8. Java8 新特性 Stream 练习实例

    练习实例 配合Java8 新特性 Steam() API 使用 //没有写get set 构造方法 public class Sku { private Integer skuId; private ...

  9. Java8 新特性Stream 的学习和使用方法

    流(Stream) 流是java 8 中新引入的特性,用来处理集合中的数据,Stream 是一个来自数据源的元素队列并支持聚合操作. Java 中 Stream 不会存储元素. 数据源 流的来源. 可 ...

  10. java8 新特性 Stream

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

随机推荐

  1. 二.django项目环境搭建

    Ⅰ.web框架介绍 1.socket 服务端 1)客户端(手机中各种app.浏览器)是用来与服务端(网站的服务器程序)进行交互的 2)服务端类似发电厂,客户端类似电器,socket类似插座,互联网的数 ...

  2. docker下安装mysql

    docker run -d -p 3306:3306 -v /root/docker/mysql/conf/mysql.cnf:/etc/mysql/conf.d/mysql.cnf -v /root ...

  3. [译]Ocelot - Routing

    原文 Ocelot主要的功能就是将http请求转发到对应的下游服务上去. Ocelot将一个请求路由到另外一个路由的动作叫做ReRoute.为了能让Ocelot能正常工作,需要在配置中设置ReRout ...

  4. KL散度

    摘自: https://www.jianshu.com/p/43318a3dc715?from=timeline&isappinstalled=0 一.解决的问题 量化两种概率分布P和Q可以使 ...

  5. spring的纯注解的IOC配置

    package config; import com.mchange.v2.c3p0.ComboPooledDataSource;import org.apache.commons.dbutils.Q ...

  6. CEYE平台的使用

    0x01 CEYE 是什么 CEYE是一个用来检测带外(Out-of-Band)流量的监控平台,如DNS查询和HTTP请求.它可以帮助安全研究人员在测试漏洞时收集信息(例如SSRF / XXE / R ...

  7. nc工具使用

    0x00 功能说明: 功能强大的网络工具,在网络工具中有“瑞士军刀”美誉,其有Windows和Linux的版本.因为它短小精悍,功能实用,被设计为一个简单.可靠的网络工具,可通过TCP或UDP协议传输 ...

  8. Junit的基础学习

    一个强大的单元测试框架: 一.组成部分: 1.注解: (1)@Test 注解: 放在测试方法上,表示这是用于测试其他方法的一个测试单元 @Test public void testSum1(){ Sy ...

  9. [转] fastText

    mark- from : https://www.jiqizhixin.com/articles/2018-06-05-3 fastText的起源 fastText是FAIR(Facebook AIR ...

  10. [Kubernetes]谈谈Kubernetes的本质

    当下k8s算是比较火的一个内容,那么它到底是什么呢,它为什么会这么火呢,它解决的是什么问题呢.这篇文章就尝试着来讲讲,Kubernetes的本质. 当我们谈Kubernetes的时候,总是会想起来Do ...