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. grafana-Admin密码重置

    1)查看Grafana配置文件,确定grafana.db的路径 [paths] ;data = /var/lib/grafana [database] # For "sqlite3" ...

  2. Python之False和None

    这个其实在Python文档当中有写了,为了准确起见,我们先引用Python文档当中的原文: In the context of Boolean operations, and also when ex ...

  3. ArrayList的实现及原理

    ArrayList ArrayList是最常见以及每个Java开发者最熟悉的集合类了,顾名思义,ArrayList就是一个以数组形式实现的集合,以一张表格来看一下ArrayList里面有哪些基本的元素 ...

  4. 【asp.net】asp.net遍历Request的信息

    #需求: 在服务端获取从客户端发送过来的所有数据信息: #方案: 1.服务端代码 public void ProcessRequest(HttpContext context) { //打印所有参数信 ...

  5. CAS实现单点登录

    1.简介 SSO单点登录 在多个相互信任的系统中,用户只需要登录一次就可以访问其他受信任的系统. 新浪微博与新浪博客是相互信任的应用系统. *当用户首次访问新浪微博时,新浪微博识别到用户未登录,将请求 ...

  6. Gram 矩阵与向量到子空间的距离

    设 $W$ 是 $n$ 维 Euclidean 空间 $V$ 的子空间, $\beta\in V$, 定义 $\beta$ 到 $W$ 的距离  $$\bex  \rd (\beta,W)=|\bet ...

  7. css Modules 使用

    我目前常用的也就是引用类名,以及在需要修改某个ui组件原有的样式比较麻烦时,会使用 :global className{ color: red;}这样来修改... 更多请参考阮老师博客: http:/ ...

  8. Scrapy框架-----爬虫

    说明:文章是本人读了崔庆才的Python3---网络爬虫开发实战,做的简单整理,希望能帮助正在学习的小伙伴~~ 1. 准备工作: 安装Scrapy框架.MongoDB和PyMongo库,如果没有安装, ...

  9. 使用tablayout和recyclerview的时候,报重复添加Fragment错误

    原因: 在添加的子Fragment报错了, 出现了空值错误, 此时报出来错误是前一个Fragment重复添加

  10. pythonのdjango CSRF简单使用

    一.简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防跨站请求伪造功 ...