Skip to content

  • 使用流,只需要说明想做什么,声明式编程,说明要做什么而不说明如何完成

        //选择再 5-20 之间从小到大不同的 7 个随机数
        new Random(47)
              .ints(5, 20)
              .distinct()
              .limit(7)
              .sorted()
              .forEach(System.out:: println);
    

  • 流的列表是一个“延迟列表”(延迟求值),可以表示非常大的序列而不需要考虑内存的问题

  • import java.util.stream.*
  • 流类型Stream<>

创建流

  • 从一组条目创建Stream.of(a,b,c...).
  • 从Collection创建Collection.stream().
  • Map要先.entrySet()生成每个对象包含一个键与其关联的值

  • 随机数流

    Random rand = new Random(47);
    rand.ints()//无参数无限流
    rand.ints(n)//一个参数表示流的大小
    rand.ints(down, up)//两个参数表示上下边界
    rand.ints(n, down, up )
    

  • 只可以生成int、long、double
  • 使用[.boxed()]打包为包装类型

  • range(from, to)

  • 生成 int 流[from, to)可以用于循环
  • for(int i:range(10,20).toArray())

  • generate()

  • 用于产生由完全相同的对象组成的流
  • 需要将一个生成对象的lambda表达式传入
    • Stream.generate(()->"duplicate")...
    • 创建一个由重复字符串组成的流
  • 也可以传入一个方法引用

  • iterate()

  • 从一个参数开始,将其传递给第二个参数引用的方法,结果添加到流并作为下一次调用的第一个参数
  • 生成斐波那契序列

    public class Fibonacci {
      int x = 1;
      Stream <Integer> numbers() {
        return Stream.iterate(0, i -> {
          int result = x + i;
          x = i;
          return result;
        });
      }
    }
    

  • 流生成器

  • 创建一个生成器对象用于生成
  • 创建Stream.Builder<String> builder = Stream.builder();
  • 使用.add()向生成起添加元素
  • 构建builder.build()构建之前可以随意添加元素

    • 直接使用build后的结果就可以获取流
  • Arrays

  • 将数组转化为流Arrays.stream(arrp[],[from, end])
  • 可以只是选择的范围
  • 对于基本类型会产生IntStream、LongStream、DoubleStream

  • 使用正则表达式切割字符串得到字符串流

  • import java.util.regex.Pattern
  • Pattern.compile("正则").splitAsStream(String);
  • 创建空流
  • Stream<String? s = Stream.empty();

  • 使用迭代器从流获取元素

    Stream <Integer> stream = new Random().ints(0, 100).boxed().distinct();
            Iterator <Integer> iterator = stream.iterator();
    

  • 通过操作迭代器进行访问

修改流元素

  • skip(n)丢弃前n个元素
  • 查看流对象peek(System.out::print)
  • 要求输入Consumer函数式接口,即没有返回值,也就不会对流修改

  • sorted([比较函数])

  • 内置比较如Comparator.reverseOrder()
  • 使用lambda(创建匿名类)

    List <Person> sortedByAge = people.stream()
        .sorted((p1, p2) -> Integer.compare(p1.getAge(), p2.getAge()))
        .collect(Collectors.toList());
    

  • 移除重复元素distinct()

  • filter()过滤元素
  • 过滤操作只保留传给过滤函数后返回值为true的元素

    public static boolean isPrime(long n){
        return rangeClosed(2,(long)Math.sqrt(n))
            .noneMath(i-> n%i==0);//有一项不满足就终止并返回 false
    }
    //生成素数
    public LongStream numbers(){
        return iterate(2, i-> i+1)
            .filter(Prime:: isPrime);
    }
    

  • map(Function)

  • 输入流中的对象,结果作为输出流继续传递
  • mapToInt(TOintFunction)等基本类型map

  • 组合流

  • 如果在map函数中生成的是流,那我们得到了一个有流组成的嵌套流
    • flatMap(Function)接受生成流的函数,并对生成的流进行扁平化展开为元素
    • flatMapToInt(Function)用于处理基础类型
  • concat()用于组合两个流

  • 从文件创建

  • 按照单词创建流
    public class FileToWords {
      public static Stream <String> stream(String filePath)
      throws Exception {
        return Files.lines(Paths.get(filePath))
          .skip(1) // First (comment) line
          .flatMap(line -> Pattern.compile("\\W+").splitAsStream(line));
          //    将对行拆分的字符串流扁平化
      }
    }
    

Optional类型

  • Optional是一个容器对象,它可能包含一个值,也可能不包含。使用Optional可以更优雅地处理可能为空的情况
  • 不只可以用于流,也可以在任何涉及null的地方使用,以减少异常,方便对null进行处理
  • 某些标准流操作会返回Optional对象
  • 流操作经常以Optional结束
  • findFirst()返回包含第一个元素的Optional,如果流为空则返回Optional.empty
  • findAny()返回包含任何元素的Optional
  • max() min()
  • 数值化流(IntStream)的average()

  • 流聚合reduce([T identity可选初始值], BinaryOperator<T> accumulator);

  • 对所有元素进行操作合并,得到聚合后的汇总结果
  • reduce(0, (a, b) -> a + b);获取元素的总和

  • 便捷函数:对Optional中的数据进行快捷操作(定义在null时进行的操作)

  • ifPresent(Consumer)如果值存在就用值来调用Consumer(一个参数没有返回值)
  • orElse(otherObject)如果对象存在则返回对象否则返回otherObject
  • orElseGet(Supplier)不存在则执行一个 Supplier 函数并返回其结果。
  • orElseThrow(Supplier)不存在则抛出由函数创建的异常

    //为 null 则怕抛出异常 
    title = Optional.ofNullable(newTitle)
          .orElseThrow(EmptyTitleException:: new);
    //为 null 则自动创建新对象
    person = Optional.ofNullable(newPerson)
          .orElse(new Person());
    

  • 创建Optional

  • 静态方法
  • Optional.empty()返回空Optional
  • of(value)要求value不是null
  • ofNullable(vlaue)允许为null,会自动返回Optional.empty

  • Optional上的操作

  • 修改

    • filter(Predicate)将函数用于Optional的内容并返回结果(返回false则转化为empty),如果Optional和函数不匹配就转化为empty(而不是直接删除)(本身就是empty则直接返回)
    • map(Function)应用Function对非empty元素进行转化
    • flatMap(Function)由提供的Function把结果包装在Optional中,flatMap不会再做任何包装(需要在Function中创建Optional)
  • Optional流

  • 创建stream.map(signal -> Optional.ofNullable(signal))
  • 获得Optional中的对象
    stream
        .filter(Optional:: isPresent)//保留非 empty
        .map(Optional:: get)获取对象
        ...
    

消费流元素

  • 接受一个流并生成最终结果,通常作为最后一件事
  • 将流转化为数组
  • toArray()自动转换到恰当类型的数组

  • 对每个流元素进行操作

  • forEach(Consumer)如输入System.out::println
    • 使用多处理器parallel()时顺序是不确定的
  • forEachOrdered(Consumer)确保按照原始流顺序进行

  • 收集

  • collect(Collector)将元素累加到一个结果集合
  • 指定生成的集合类型collect(Collectors.toCollection(TreeSet::new))

    public class TreeSetOfWords {
      public static void
      main(String [] args) throws Exception {
        Set <String> words2 =
          Files.lines(Paths.get("TreeSetOfWords.java"))
            //根据非单词字符划分
            .flatMap(s -> Arrays.stream(s.split("\\W+")))
            //去除非数字
            .filter(s -> ! s.matches("\\d+")) // No numbers
            //去除左右空白
            .map(String:: trim)
            //去除太短
            .filter(s -> s.length() > 2)
            .limit(100)
    //指定生成的集合类型        
    .collect(Collectors.toCollection(TreeSet:: new));
        System.out.println(words2);
      }
    }
    

  • 转化为mapCollectors.toMap(获取key的函数,获取val的函数)

  • 大部分时候都可以直接使用预定义的Collector
  • collect(Supplier, BiConsumer, BiConsumer)创建新集合,将下一个元素包含到结果中,将两个值组合起来
  • collector(ArrayList::new,ArrayList::add,ArrayList::addAll)

  • 组合

  • reduce([identity(组合的初始值),] BinaryOperator)组合所有流元素,返回Optional

  • 匹配

  • allMatch(Predicate)每一个元素都是true才返回true
  • anyMatch(Predicate)任何一个为true就返回true
  • noneMatch(Predicate)没有true
  • 都是短路计算

  • 选择

  • findFirst()
  • findAny()对于非并行的流也是返回第一个
  • 获取最后一个元素reduce((n1,n2)->n2)

  • 获取信息

  • count()元素数目
  • max(Comparator)
    • 许多类型有预定义的比较器,如String.CASE_INSENSITIVE_ORDER
    • 数值化流不需要比较器
  • min(Comparator)
  • 数值化流
    • average()
    • sum()
    • summaryStatistics() 获取摘要数据 (用于查看数值流的状态)