Java8 Stream使用教程

什么是Stream

   stream是对集合(Collection)对象功能的增强,它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。

   原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。

流的构成

获取一个流,通常有三个步骤:

  获取一个数据源(source)→ 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道

有多种方式生成 Stream Source:

  • 从 Collection 和数组
    • Collection.stream()
    • Collection.parallelStream()
    • Arrays.stream(T array) or Stream.of()
  • 从BufferedReader
    • java.io.BufferedReader.lines()
  • 静态工厂
    • java.util.stream.IntStream.range()
    • java.nio.file.Files.walk()

流的操作类型分为两种:

  • Intermediate: 一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。

  • Terminal: 一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

流的构造与转换

构造流的几种常见方法
  // 1. Individual values

  Stream stream = Stream.of("a", "b", "c");

  // 2. Arrays

  String [] strArray = new String[] {"a", "b", "c"};

  stream = Stream.of(strArray);

  stream = Arrays.stream(strArray);

  // 3. Collections

  List<String> list = Arrays.asList(strArray);

  stream = list.stream();
流转换为其它数据结构

一个 Stream 只可以使用一次,下面面的代码为了简洁而重复使用了数次。

  // 1. Array
  String[] strArray1 = stream.toArray(String[]::new);

  // 2. Collection
  List<String> list1 = stream.collect(Collectors.toList());

  List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));

  Set set1 = stream.collect(Collectors.toSet());

  Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));

  // 3. String
  String str = stream.collect(Collectors.joining()).toString();

流的操作

  • Intermediate:
    map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

      // map/flatMap 
      // Stream中map元素类型转化方法
      List<User> collect = userList.stream().map(user -> fixUser(user)).collect(Collectors.toList());
    
      // filter 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。
      // 过滤掉不满足条件的对象
      userList.stream().filter(user -> user.getAge()<20).forEach(user -> System.out.println("filter" + user));
    
      //peek 对每个元素执行操作并返回一个新的 Stream
      userList.stream().peek(System.out::println)
    
      //findFirst 这是一个 terminal 兼 short-circuiting 操作,它总是返回 Stream 的第一个元素,或者空。
      Optional<User> first = userList.stream().findFirst();
      User user = first.get();
    
      // limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素
      userList.stream().limit(1).forEach(user -> System.out.println("limit: " + user));
      userList.stream().skip(2).forEach(user -> System.out.println("skip: " + user));
    
      //sort 排序 根据某个值排序取前几个
      userList.stream().sorted(Comparator.comparing(User::getAge)).limit(2).forEach(user -> System.out.println("sorted: " + user));
    
      // min/max/distinct  min 和 max 的功能也可以通过对 Stream 元素先排序,再 findFirst 来实现,但前者的<性能会更好,为 O(n),而 sorted 的成本是 O(n log n)。同时它们作为特殊的 reduce 方法被独立出来也是因为求最大最小值是很常见的操作。
      BufferedReader bufferedReader = new BufferedReader(new FileReader("E:\\文档\\笔记\\node的安装及使用.md"));
      int asInt = bufferedReader.lines().mapToInt(String::length).max().getAsInt();
      // 找出全文的单词,转大写,并排序
          List<String> strings = br.lines().flatMap(line -> Stream.of(line.split(" ")))
                  .filter(word -> word.length() > 0).map(String::toUpperCase).distinct().sorted()
                  .collect(Collectors.toList());
    
  • Terminal:
    forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

      //forEach  forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。
      userList.stream().filter(user -> user.getAge()>18).forEach(System.out::println);
    
    
  • Short-circuiting:
    anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

    Stream 有三个 match 方法,从语义上说:

    • allMatch:Stream 中全部元素符合传入的 predicate,返回 true
    • anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
    • noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
      // 是否有所有人都大于18岁
      boolean b = userList.stream().allMatch(uesr -> uesr.getAge() > 18);
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值