java-stream

java8-Stream

什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源* 流的来源。 可以是集合数组I/O channel产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现

​ ————————以上是菜鸟教程的说明

接下来还是菜鸟教程的内容

首先是生成流的类别

  • 串行流 stream()
  • 并行流 parallelStream()

串行流

首先来看一下一个小的demo

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<String> filtered = strings.stream()
                        .filter(string -> !string.isEmpty())
                        .collect(Collectors.toList());
filtered.forEach(System.out::println);

输出结果:
abc
bc
efg
abcd
jkl

forEach

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

用ints()生成的对象是 IntStream 类型的对象,是int值流
  • random.ints()
    • 用于得到一个有效无限的伪随机 int 值流
      • 带有一个参数的时候,得到传入参数个的有效无限的伪随机int值流
      • 带有两个参数的时候,得到在这个范围内的int流值,如果不设置limit(个数)的话,会无限生成
  • limit()
    • 用来限制生成多少个值(在此处的理解)

map

map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
squaresList.forEach(System.out::println);
结果:
9
4
49
25
  • distinct() 此函数是用来去重的函数

filter

filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
 List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<String> list = strings.stream().filter(string->!string.isEmpty()).map(string->
" "+string+" ").collect(Collectors.toList());
list.forEach(System.out::println);
输出结果:
 abc 
 bc 
 efg 
 abcd 
 jkl 

可以多个方法链式使用,以达到自己的目的

collect(Collectors.toList())将自己的流数据冲到list集合里面去

limit

limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
输出结果:
-1560117986
-1364889229
-1336273802
-1272156577
-1143677960
-659024975
-520656633
1433415374
1633707646
1972427861

  • 显然使用sorted()方法对结果集默认使用的是从小到大进行排序
/**
* Returns a stream consisting of the elements of this stream in sorted
* order.
*
* <p>This is a <a href="package-summary.html#StreamOps">stateful
* intermediate operation</a>.
*
* @return the new stream
*/
IntStream sorted();
官方给的说明

如果想使用逆序排序的话

此博客上找出了可以实现的方法

由此展开说明

  • 首先是如果元素类想使用sorted进行排序,则元素类必须实现Comparable接口

  • 自然降序则需要使用Comparator.reverseOrder()作为sorted的参数

  • List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
    list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
    输出结果:
    7
    6
    5
    4
    3
    2
    1
    
  • 如果想对自己定义的类进行排序,可以参照上方的博客进行细读和研讨

统计

另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
输出结果:
列表中最大的数 : 7
列表中最小的数 : 2
所有数之和 : 25
平均数 : 3.5714285714285716

并行(parallel)程序

parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
// 获取空字符串的数量
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();

System.out.println(count);
输出结果:
2

看上去并没有什么不同的,但是既然说并行处理的话,就找多个数据进行输出处理来进行尝试

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.parallelStream().forEach(System.out::println);
输出结果:
6
3
5
4
2
1
8
7
9
结果显而易见,数序发生了错误,接下来打印线程信息来验证
numbers.parallelStream() .forEach(num->System.out.println(Thread.currentThread().getName()+"->"+num));
输出结果:
ForkJoinPool.commonPool-worker-1->3
ForkJoinPool.commonPool-worker-1->4
ForkJoinPool.commonPool-worker-1->2
ForkJoinPool.commonPool-worker-1->1
ForkJoinPool.commonPool-worker-1->8
ForkJoinPool.commonPool-worker-1->9
ForkJoinPool.commonPool-worker-1->7
ForkJoinPool.commonPool-worker-1->5
main->6

根据以上的输出结果可知,parallelStream是利用多线程来进行的,可以简化我们对并发操作的使用

参考 圆圆同学的博客

剩下的一些以后再做补充,如果有疑问或者看法请随时联系

posted @ 2019-11-17 10:03  atomFix  阅读(201)  评论(0编辑  收藏  举报