铁匠 铁匠
首页
收藏
java
架构之路
常用算法
  • Java
  • nginx
  • 系统运维
  • 系统安全
  • mysql
  • redis
参考文档
关于
链接
  • 分类
  • 标签
  • 归档

专注、不予评判地关注当下
首页
收藏
java
架构之路
常用算法
  • Java
  • nginx
  • 系统运维
  • 系统安全
  • mysql
  • redis
参考文档
关于
链接
  • 分类
  • 标签
  • 归档
  • java api 文档
  • 集合

  • 版本特性

    • java8

      • Lambda表达式与函数式接口
      • 新的Date&Time API
      • 方法引用
      • Stream(流)
        • 什么是Stream
        • 创建流
        • 处理流
          • 筛选与切片
          • 映射 - 将数据映射成其他类型的数据
          • 排序
        • 终止流
          • 匹配
          • 查找
          • 统计
          • 迭代
          • 聚合
          • 收集
        • 示例
      • optional
  • jvm

  • 网络编程

  • 并发编程

  • java
  • 版本特性
  • java8
FengJianxin
2019-08-12
目录

Stream(流)

# 什么是Stream

Java8添加了一个新的接口Stream(流),可以用函数式风格对数据进行处理。就像写sql语句一样。

流处理过程

+--------+     +--------+     +--------+ 
| 创建流  |+--->| 处理流  |+--->| 终止流  |
+--------+     +--------+     +--------+ 
1
2
3

流处理特点:

  • 不保存数据
  • 不修改数据
  • 延迟处理,在获得结果的时候才会执行中间数据处理操作

流类型

  • stream() − 创建串行流。
  • parallelStream() − 创建并行流(内部使用Fork/Join线程模型处理)

# 创建流

流的数据源可以是:集合、数组、迭代器、生产器等

// list转stream
List<String> strList = new ArrayList<>();
Stream<String> listStream = strList.stream();

// 数组转stream
String[] strArr = new String[10];
Stream<String> arrStream = Arrays.stream(strArr);

// 通过静态方法创建流
Stream<String> stream = Stream.of("a", "b", "c");

// 通过种子创建无限流
Stream<Integer> iterStream = Stream.iterate(2, i -> i * i);
/* 
 * 2
 * 4
 * 8
 * 16
 * ...
 */

// 创建10个元素的流
Stream<Integer> iter10Stream = Stream.iterate(2, i -> i * 2).limit(3);
iter10Stream.forEach(System.out::println);
/* 
 * 2
 * 4
 * 8
 */

// 生产
Stream<Double> genStream = Stream.generate(Math::random).limit(3);
genStream.forEach(System.out::println);
/* 
 * 0.5875071685084056
 * 0.622271393744705
 * 0.7873169115032873
 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 处理流

流的处理就像流水线一样,按照流程一步步处理下去

# 筛选与切片

  • filter(Predicate p) - 过滤掉不符合条件的数据
  • distinct() - 数据去重(使用hashCode和equals判断是否是相同数据)
  • limit(long maxSize) - 截断操作,当已经获得maxSize个数据后,将不再继续筛选数据
  • skip(long n) - 跳过前n个数据,如果数据不足n个,则返回一个空流

# 映射 - 将数据映射成其他类型的数据

  • map(Function<? super T, ? extends R> mapper) - 将数据映射成新的类型
  • mapToInt(ToIntFunction<? super T> mapper) - 将数据映射成Integer类型
  • mapToLong(ToLongFunction<? super T> mapper) - 将数据映射成Long类型
  • flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) - 将数据映射另外一个流,并将每个数据映射的流合并成一个流

# 排序

  • sorted() - 字典排序
  • sorted(Comparator<? super T> comparator) - 自定义排序

# 终止流

从一系列中间操作获得最终数据

# 匹配

  • allMatch(Predicate<? super T> predicate) - 是否所有元素匹配
  • anyMatch(Predicate<? super T> predicate) - 是否有至少一个数据匹配
  • noneMatch(Predicate<? super T> predicate) - 是否没有数据匹配

# 查找

  • findFirst() - 返回第一个数据
  • findAny() - 返回任一数据

# 统计

  • count() - 返回数据总数
  • max(Comparator<? super T> comparator) - 返回数据的最大值
  • min(Comparator<? super T> comparator) - 返回数据的最小值

# 迭代

  • forEach(Consumer<? super T> action) - 内部跌倒方式获取数据

# 聚合

  • reduce(BinaryOperator< T> accumulator) - 将数据聚合后获得一个新值,返回值是Optional类型
  • reduce(T identity, BinaryOperator< T> accumulator) - 通过起始值identity将数据聚合后获得获得一个新的值

# 收集

  • collect(Collector<? super T, A, R> collector) - 通过Collector接口,将数据收集成一个非Stream类型的集合

提示

可以用Collectors静态方法来创建Collector对象

  • toList: 将数据转成List
  • toSet: 将数据转成Set
  • toMap: 将数据转成Map
  • averagingDouble: 求数据平均值
  • groupingBy: 对数据进行分组

其他更多方法查看Collectors api

# 示例

public static void main(String[] args) {
    List<String> strList = Arrays.asList("a", " ", "sas", "1", "39", "as234",
        "nba", "cba", "32", "25", "ss ", " srr ", "10", "", " bqwe");

    // 查找出全部数字,按照字典排序,并将结果收集到List<Integer>
    List<Integer> intList = strList.stream()
        .filter(str -> str.trim().length() > 0)
        .filter(str -> isInteger(str))
        .map(str -> Integer.parseInt(str))
        .sorted()
        .collect(Collectors.toList());
        System.out.println(intList);

    // 查找出所有数字中最大的值是多少
    Optional<Integer> max = strList.stream()
        .filter(str -> str.trim().length() > 0)
        .filter(str -> isInteger(str))
        .map(str -> Integer.parseInt(str)).max((a, b) -> a - b);
    System.out.println("max: " + max.get());

    // 查找出所有数字的总和
    Optional<Integer> sum = strList.stream()
        .filter(str -> str.trim().length() > 0)
        .filter(str -> isInteger(str))
        .map(str -> Integer.parseInt(str))
        .reduce((a, b) -> a + b);
    System.out.println("sum: " + sum.get());

    // 查找出所有数字的个数
    long count = strList.stream()
        .filter(str -> str.trim().length() > 0)
        .filter(str -> isInteger(str))
        .map(str -> Integer.parseInt(str))
        .count();
    System.out.println("count: " + count);

    // 查找出所有数字的平均值
    Double ave = strList.stream()
        .filter(str -> str.trim().length() > 0)
        .filter(str -> isInteger(str))
        .map(str -> Integer.parseInt(str))
        .collect(Collectors.averagingInt(value -> value));
    System.out.println("ave: " + ave);

    // 去掉所有字符串两边空格,并获得所有以字母a开头的字符串
    strList.stream()
        .map(str -> str.trim())
        .filter(str -> str.startsWith("a"))
        .filter(str -> !isInteger(str))
        .forEach(System.out::println);
}

public static boolean isInteger(String str) {  
    Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");  
    return pattern.matcher(str).matches();  
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#java8
方法引用
optional

← 方法引用 optional→

最近更新
01
策略模式
01-09
02
模板方法
01-06
03
观察者模式
01-06
更多文章>
Theme by Vdoing | Copyright © 2016-2023 铁匠 | 粤ICP备15021633号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式