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. Java斗地主案例、异常和自定义异常整理

    模拟斗地主洗牌发牌 1.1 案例介绍 按照斗地主的规则,完成洗牌发牌的动作. 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张 ...

  2. 第九节: 利用RemoteScheduler实现Sheduler的远程控制

    一. RemoteScheduler远程控制 1. 背景: 在A服务器上部署了一个Scheduler,我们想在B服务器上控制这个Scheduler. 2. 猜想: A服务器上的Scheduler需要有 ...

  3. mysql数据库truncate表时间长处理

    [环境介绍] 系统环境:Linux + mysql 5.7.18 + 主从复制架构 [背景描述] 客户反映用在mysql数据库上truncate一个innode引擎的list分区100G左右表时,耗时 ...

  4. [Tex学习笔记]小于等于一个常数乘以...

    偏微分的论文中常用: 小于等于一个常数乘以... 这个要怎么输入呢. 只要输入\lesssim 就能得到 $\lesssim$...哈哈. 以前知道, 但是忘记了. 现在又要用.

  5. [再寄小读者之数学篇](2014-06-26 Besov space estimates)

    (1) $$\bex \sen{D^k f}_{\dot B^s_{p,q}}\sim \sen{f}_{\dot B^{s+k}_{p,q}}. \eex$$ (2) $$\beex \bea &a ...

  6. densenet 中的shortcut connection

    DenseNet  在FCN 网络中考虑加入skip connection,在resnet 中加入identity 映射,这些 shortcut connection等结构能够得到更好的检测效果,在d ...

  7. sessionStorage数组、对象的存储和读取

    一个对象的demo如下: var obj = { name:"name", age:18, love:"美女" } sessionStorage.setItem ...

  8. Ch02 课堂作业

    测试一:运行结果: 测试二:运行结果: 测试三:运行结果:

  9. DeepLearning.ai学习笔记(四)卷积神经网络 -- week4 特殊应用:人力脸识别和神经风格转换

    一.什么是人脸识别 老实说这一节中的人脸识别技术的演示的确很牛bi,但是演技好尴尬,233333 啥是人脸识别就不用介绍了,下面笔记会介绍如何实现人脸识别. 二.One-shot(一次)学习 假设我们 ...

  10. Android串口通信(Android Studio)

    gilhub上已有开源项目: https://github.com/cepr/android-serialport-api 可以直接使用