Java8新特性之Stream流

1. 集合流的简介

1.1. 集合的流式编程的简介

Stream是JDK1.8之后出现的新特性,也是JDK1.8新特性中最值得学习的两种新特性之一。(另外一个是lambda表达式)。
Stream是对集合操作的增强,流不是集合的元素,不是一种数据结构,不负责数据的存储的。流更像是一个迭代器,可以单向的追历一个集合中的每一个元素,并且不可循环

1.2. 为什么要使用集合的流式编程

有些时候,对集合中的元素进行操作的时候,需要使用到其他操作的结果。在这个过程中,集合的流式编程可以大幅度的简化代码的数量,将数据源中的数据,读现到一个流中,可以对这个流中的数据进行操作(删除、过滤、映射…)。每次的操作结果也是一个流对象,可以对这个流再进行其他的操作。

1.3. 使用流式编程的步骤

通常情况下,对集合中的数据使用流式编程,需要经过以下三步。

  1. 获取数据源,将数据源中的数据读取到流中。
  2. 对流中的数据进行各种各样的处理。
  3. 对流中的数据进行整合处理。

​ 在上述三个过程中,过程2中,有若干方法,可以对流中的数据进行各种各样的操作,并且返回流对像本身,这样的操作,被称为 —— 中间操作。过程3中,有若干方法,可以对流中的数据进行各种处理,并关闭流,这样的操作,被称为 —— 最终操作。

​ 在中间操作和最终操作中,基本上所有的方法参数都是函数式接口,可以使用lambda表达式来实现。使用集合的流式编程,来简化代码量,是需要对lanbda表达式做到熟练掌握。

2. 数据源的获取

2.1. 数据源的简介

数据源,顾名思义,既是流中的数据的来源,是集合的流式编程的第一步,将数据源中的数据读取到流中,进行处理。注意:将数据读取到流中进行处理的时候,与数据源中的数据没有关系。也就是说,中间操作对流中的数据进行处理、过滤、映射、排序 . . . ,此时是不会影响数据源中的数据的。

2.2. 数据源的获取

​ 这个过程,其实是将一个容器中的数据,读取到一个流中。因此无论什么容器作为数据源,读取到流中的方法返回值一定是一个Stream。

// 1.通过Collection接口中的stream()方法获取数据源为Collection的流
Stream<Integer> stream= list.stream();
// 2.通过Collection接口的parallelstream()方法获取数据源为Collection的流
Stream<Integer> stream = list.parallelStream();
// 3.通过Arrays工具类中的stream()方法获取数据源为数组(Integer数组)的流
Stream<Integer> stream = Arrays.stream(array);
// 4.通过Arrays工具类中的stream()方法获取数据源为数组(int数组)的流
IntStream stream = Arrays.stream(array);

关于stream()parallelStream()
他们都是Collection集合获取数据源的方法,不同点在于stream()方法获取的数据源是串行的,parallelStream()获取的数据源是并行的,parallelStream()内部集成了多个线程对流中的数据进行操作,效率更高。

3. 最终操作

3.1. 最终操作的简介

将流中的数据整合到一起,可以存入一个集合,也可以直接对流中的数据进行遍历、数据统计…,通过最终操作,需要掌握如何从流中提取出来我们想要的信息。
注意事项∶最终操作,之所以叫最终操作,是因为,在最终操作执行结束后,会关闭这个流,流中的所有数据都会销毁。如果使用一个已经关闭了的流,会出现异常。

3.2. collect 收集

​ 将流中的数据收集到一起,对这些数据进行一些处理。最常见的处理,就是将流中的数据存入一个集合。collect方法的参数,是一个Collector接口,而且这个接口并不是一个函数式接口。实现这个接口,可以自定义收集的规则。但是,绝大部分情况下,不需要自定义。

​ 直接使用Collectors工具类提供的方法即可。

List<Integer> collect = list.stream().collect(Collectors.toList());
Set<Integer> collect = list.stream().collect(Collectors.toSet());
Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Objects::toString, i -> i));

3.3. reduce 聚合

​ 将流中的数据按照—定的规则聚合起来。

// 将流的元素,逐一带入到这个方法中,进行运算
// 最终的运算结果,得到的其实是一个Optional类型,需要使用get()获取到里面的数据
// Integer integer = list.stream().reduce((a, b) -> a + b).get();
Integer integer = list.stream().reduce(Integer::sum).get();

3.4. count 统计

​ 统计流中的元素数量。

long count = list.stream().count();

3.5. forEach 遍历

​ 迭代、遍历流中的数据。

list.stream().forEach(System.out::println);

3.6. max & min 最值

​ 获取流中的最大的元素、最小的元素。

// 获取最大值
Integer max = list.stream().max(Integer::compareTo).get();
// 获取最小值
Integer max = list.stream().min(Integer::compareTo).get();

3.7. Matching 匹配

  • allMathch:只有当流中所有的元素,都匹配指定的规则,才会返回 true
  • anyMatch:只要流中有任意的数据,满足指定的规则,都会返回 true
  • noneMatch:只有当流中的所有的元素,都不满足指定的规则,才会返回 true
// 判断流中是否所有的元素都大于 50
boolean ans = list.stream().allMatch(ele -> ele > 50);

// 判断流中是否有大于 50 的数据
boolean ans = list.stream().anyMatch(ele -> ele > 50);

// 判断流中是否没有奇数
boolean ans = list.stream().noneMatch(ele -> ele % 2 != 0);

3.8. find 获取

  • findFirst:从流中获取一个元素(一般情况下,是获取的开通的元素)
  • findAny:从流中获取一个元素(一般情况下,是获取的开头的元素)

这两个方法,绝大部分情况下,是完全相同的,但是在多线程的环境下,findAny和find返回的结果可能不一样。

Integer ans = list.parallelStream().findFirst().get();

Integer ans = list.parallelStream().findAny().get();

3.9. IntStream的最终操作

注意:IntStream和DoubleStream等一样的方法。

int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
IntStream stream = Arrays.stream(array);
int max = stream.max().getAsInt();					// 获取最大值
int min = stream.min().getAsInt();					// 获取最小值
int sum = stream.sum();								// 获取数据和
int count = stream.count();							// 获取流中的数据数量
double average = stream.average().getAsDouble();	// 获取流中数据的平均值
IntSummarystatistics intSummaryStatistics = stream.summaryStatistics();	// 获取流中数据的分析结果,包括上述所有的值。

4. 中间操作

4.1. 中间操作的简介

将数据从数据源中读取到流中,中间操作,就是对流中的数据进行各种各样的操作、处理。中间操作可以连续操作,每一个操作的返回值都是一个stream对象,可以继续进行其他的操作。直到最终操作。

4.2. filter 过滤

条件过滤,仅保留流中满足指定条件的数据,其它不满足的数据都会被删除。

list.stream().filter(ele -> ele.length() > 5).forEach(System.out::println);

4.3. distinct 去重

去重集合中重复的元素。这个方法没有参数。去重的规则与HashSet相同。

list.stream().distinct().forEach(System.out::println);

4.4. sorted 排序

将流中数据进行排序

// 按照流中的元素对应的类实现的 Comparable 接口中的方法实现排序
list.stream().sorted().forEach(System.out::println);
// 将流中的数据,按照指定的规则进行排序
list.stream().sorted((e1,e2) -> e1.length()-e2.length()).forEach(System.out::println);

4.5. limit & skip

limit : 限制,表示截取流中指定数量的数据

skip:跳过,可以跟限制配合使用

// 获取流中第三个到第五个
list.stream().skip(2).limit(3).forEach(System.out::println);
// 获取流中第三个到第五个
list.stream().limit(5).skip(2).forEach(System.out::println);

4.6. map & flatMap

map:对流中的数据进行映射,用新的数据替换旧的数据。

list.stream().map(ele -> ele + ".txr").forEach(System.out::println);

map最主要,就是来做元素的替换。其实map是一个元素的映射。

flatMap也是元素的映射,flatMao是扁平化映射。

扁平化映射:一般在map映射完成后,流中的数据是一个容器,而我们需要对容器中的数据进行处理,此时使用扁平化映射,可以将流中的容器中的数据,直接读取到流中。

// 1. 实例化一个字符串数组
String[] array = {"hello","world"};
// 2. 将字符串数组中的数据读取到流中
Stream<String> stream = Arrays.stream(array);
// 3. 需求:统计字符串数组中所有出现的字符
stream.map(s -> s.split(""))
    .flatMap(Arrays::stream)
    .distinct()
    .forEach(System.out::println);

5. Collectors工具类

5.1. 概念

Collectors是一个工具类,里面封装了很多方法,可以很方便的获取到一个Collector接口的实现类对象,从而可以使用col1ect()方法,对流中的数据,进行各种各样的处理、整合。

5.2. 常用方法

方法描述
Collectors.toList()将流中的数据,聚合到一个 List 集合中
Collectors.toSet()将流中的数据,聚合到一个 Set 集合中
Collectors.toMap()将流中的数据,聚合到一个 Map 集合中
maxBy()按照指定的规则,找到流中最大的元素,等同于 max
minBy()按照指定的规则,找到流中最小的元素,等同于 min
joining()将流中的数据评价成一个字符串,注意:只能操作流中是String的数据
summingInt()将流中的数据,映射成 int 类型的数据,并求和
averagingInt()将流中的数据,映射成 int 类型的数据,并求平均值
summarizingInt()将流中的数据,映射成 int 类型的数据,并获取描述信息
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值