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. secureCRT自动断开的解决方法

    转: secureCRT自动断开的解决方法 secureCRT自动断开的解决方法 在secureCRT上登录时,一段时间不用的话会自动断开,必须重新连接,有点麻烦. 有时候服务器端的 /etc/pro ...

  2. .pyc是个什么 python的执行过程

    1. Python是一门解释型语言? 我初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存在.如果是解释型语言, ...

  3. Numpy 系列(九)- 结构化数组

      简介 之前我们操作Numpy的数组时,都是通过索引来操作的.针对二维数组,使用索引可以完成对行.列的操作.但是这是非常不直观的.可以把二维数组想象成一个excel表格,如果表格没有列名,操作起来会 ...

  4. 金融量化分析【day113】:聚宽自带策略

    一.策略代码 # 导入函数库 from jqdata import * # 初始化函数,设定基准等等 def initialize(context): # 设定沪深300作为基准 set_benchm ...

  5. React 记录(6)

    React文档:https://www.reactjscn.com/docs/react-component.html 慢慢学习:对照教程文档,逐句猜解,截图 React官网:https://reac ...

  6. Vim使用技巧汇总

    一 写在开头 1.1 本文内容 Vim使用技巧与学习资源汇总. 二 Vim学习资源 1. Vimtutor 2. Vim中文帮助(http://vimcdoc.sourceforge.net/doc/ ...

  7. VS2012/2013/2015/Visual Studio 2017 关闭单击文件进行预览的功能

    Visual Studio在2010版本后推出了点击项目管理器预览文件的功能,但是对于配置不咋地的旧电脑总是觉得有点卡,下面是解决方案. 英文版方法:Tools->Options->Env ...

  8. ArcGis 属性表.dbf文件使用Excel打开中文乱码的解决方法

    2019年4月 拓展: ArcGis——好好的属性表,咋就乱码了呢? 2019年3月27日补充: 在ArcMap10.3+(根据官网描述应该是,作者测试使用10.5,可行)以后的版本,可以使用ArcT ...

  9. LOJ #556. 「Antileaf's Round」咱们去烧菜吧

    好久没更博了 咕咕咕 现在多项式板子的常数巨大...周末好好卡波常吧.... LOJ #556 题意 给定$ m$种物品的出现次数$ B_i$以及大小$ A_i$ 求装满大小为$[1..n]$的背包的 ...

  10. javascript没有长整型

    记录一下前几天踩坑的经历. 背景:一个项目某一版之后很多用easyui的表格控件treegrid渲染的表格都显示不出来了 奇怪的地方主要有以下几点: 项目在测试环境才会这样,在本机能够正常运行,多次重 ...