四时宝库

程序员的知识宝库

Java Stream从入门到精通之简介(一)

@SpringBootTest(classes =
                Application.class,  
                webEnvironment = 
                SpringBootTest.WebEnvironment.RANDOM_PORT)
public class StreamIntroduction {
  /*一.Java Stream操作=======*/    
  //1. 外部迭代-----------------------
  /**     
  * Java 8 之前,在操作Java集合时,
  * 我们使用外部迭代。在外部迭代中,
  * 我们为每个循环使用for或,或者
  * 为集合获取一个迭代器,并按顺
  * 序处理集合的元素。下面的代码
  * 计算列表中所有奇数的平方和。
  * 它使用每个循环访问列表中的每
  * 个元素,然后使用if语句过滤奇数。
  * 然后计算平方,最后用sum变量
  * 存储平方的和。     
  */    
    @Test
    public void test00() {
        List<Integer> numbers = 
          Arrays.asList(1, 2, 3, 4, 5);       
        int sum = 0;        
        for (int n : numbers) {
            if (n % 2 == 1) {
                int square = n * n;                
                sum = sum + square;           
            }
        }
        System.out.println(sum);    
    }
    //2. 内部迭代----------------------
   /**     
   * 在上面的代码中,我们没有使用
   * loop语句来遍历列表。我们通过
   * 流在内部执行循环。对于奇整数
   * 的计算,我们使用lambda表达式。
   * 我们首先做过滤器, 然后映射,
   * 然后减少。    
   */    
    @Test
    public void test01() {
        List<Integer> numbers = 
                Arrays.asList(1, 2, 3, 4, 5);        
        int sum = numbers.stream()
      )//过滤(后面会讲到)
                .filter(n -> n % 2  == 1                
                .map(n  -> n * n)//映射
                //累加          
                .reduce(0, Integer::sum);     
      System.out.println(sum);    
    }
    //3.序列-------------------------
    /**     
    * 外部迭代通常意味着顺序代码。
    * 顺序代码只能由一个线程执行。
    * 流被设计成并行处理元素。    
    * 下面的代码并行计算列表中奇
    * 数的平方和。我们所做的只是
    * 将stream()替换为parallelStream()。    
    */    
    @Test
    public void test02() {
        List<Integer> numbers = 
                  Arrays.asList(1, 2, 3, 4, 5);        
        int sum = numbers.parallelStream()
                .filter(n -> n % 2  == 1)
                .map(n  -> n * n)
                .reduce(0, Integer::sum);        
      System.out.println(sum);    
    }
    //4. 命令式和函数式----------- 
    /**     
    * 在命令式编程中,我们不仅控制做
    * 什么,而且控制如何做。例如,
    * 在使用命令式编程对列表中的整数
    * 进行求和时。     
    * 我们必须决定如何迭代列表中的每
    * 个元素。我们可以使用for循环,
    * for-each循环,或者我们可以从
    * list中获得一个迭代器对象并
    * 使用while循环。     
    * 然后我们还要计算和。在声明式
    * 编程中,我们只需要告诉要做什么,
    * 系统本身如何处理这部分。
    * 集合支持命令式编程,
    * 而流支持声明式编程。     
    * StreamIntroduction API通过
    * 使用lambda表达式支持函数式编程。
    * 我们想对流元素执行的操作通常是
    * 通过传递一个lambda表达式来完成的。     
    * 流上的操作生成不修改数据源的
    * 结果(peek除外)。     
    */    
    //5. 中间操作终端操作-------------
    /**     
    * 流支持两种类型的操作:     
    *  中间操作(惰性操作):延迟操作
    * 在流上调用急于操作之前不会处理
    * 元素。指的是操作最终不会产生新的集合。     
    *  终端操作(即时操作):一个流上的
    * 中间操作会产生另一个流。指的是操作
    * 会产生新的集合。     
    * Streams链接操作以创建流管道。
    * 在下面的代码中,filter()和map()都是
    * 惰性操作。而reduce()是即时操作。     
    */    
    @Test
    public void test03() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);        
        int sum = numbers.parallelStream()
                .filter(n -> n % 2  == 1)
                .map(n  -> n * n)
                .reduce(0, Integer::sum);        
        System.out.println(sum);    
    }
    /*二.Java Stream API ========*/    
    /**     
    * Stream相关的接口和类在java.util包
    * 中。AutoCloseable接口来自
    * java.lang包。所有Stream接口都
    * 继承自BaseStream接口,     
    * 而BaseStream接口继承自
    * AutoCloseable接口。     
    * AutoCloseable     
    *  |     
    *  +--BaseStream     
    *      |     
    *      +--IntStream     
    *      |     
    *      +--LongStream     
    *      |     
    *      +--DoubleStream     
    *      |     
    *      +--Stream<T>     
    *  如果Stream使用集合作为其数据源,
    * 并且集合不需要关闭。     
    * 如果Stream基于可关闭的数据源
    * (如文件I/O通道),我们可以使用
    * try-with-resources语句创建Stream,
    * 使其自动关闭。     
    * 1. BaseStream     
    *  BaseStream接口定义了所有
    * Stream通用的所有方法。     
    *  -- Iterator<T> Iterator() 终端操作,
    * 返回流的迭代器。     
    *  -- sequential() 中间操作,
    * 返回一个串行流。如果流已经
    * 是串行,它就返回自己。
    * 它将并行流转换为顺序流。     
    *  -- parallel() 中间操作,
    * 返回并行流。如果流已经是
    * 并行的,它就返回自己。
    * 它将并行流转换为顺序流。     
    *  -- boolean isParallel() 如果流
    * 是并行的,返回true,否则返回
    * false。在调用终端流操作方法
    * 之后调用此方法可能会产生不
    * 可预测的结果。     
    *  -- unordered() 中间操作,
    * 返回流的无序版本。如果流已经
    * 是无序的,它将返回自己。     
    * 2.Stream     
    *      Stream<T>接口表示元素类
    * 型为T的流。Stream<Student>
    * 表示学生对象流。Stream<T>接口
    * 包含filter()、map()、reduce()、     
    *  collect()、max()、min()等方法。
    * 在使用基本类型时,我们可以使用
    * 三个专门的流接口,即IntStream、
    * LongStream和DoubleStream。     
    *  这些接口提供了处理基本值的方法。
    对于其他基本类型,如float、short、
    * byte,我们仍然可以使用这三种专用
    * 流接口。     
    *  在下面的代码中,我们将使用stream
    * 计算列表中所有奇数的平方和。     
    *  我们将使用以下步骤进行计算。     
    *  2.1 创建Stream     
    *      集合接口中的stream()方法返回
   * 一个顺序流。在这种情况下,
   * 集合充当数据源。下面的代码创建了
   * 一个列表<Integer>,     
   *      并从列表中获得一个流<Integer>:     
   *      List<Integer>  numbersList = Arrays.asList(1, 2, 3, 4, 5);     
   *      Stream<Integer> numbersStream  = numbersList.stream();     
   *  2.2 过滤Stream     
   *      Stream<T> filter()使用指定谓词返回
   * true时来保留流中的元素。下面的语句得到了一个奇数流:     
   *      Stream<Integer> oddNumbersStream= 
   * numbersStream.filter(n -> n % 2 == 1);     
   *  2.3 映射Stream     
   *      Stream<T> map()使用一个函数映射流
   * 中的每个元素并创建一个新的流。     
   *      Stream<Integer> aStream = 
   * stream.map(n -> n * n);// n = n * n     
   *  2.4 规约Stream     
   *      reduce(T identity, BinaryOperator<T> accumulator) 
   * 将流减少为单个值。接受一个初始值和一个二进制运算符<T>的     
   *      累加器作为参数。使用提供的初始值
   * 和关联累积函数对该流的元素执行减少,并返回减少的值。     
   *      int sum = aStream.reduce(0, (n1, n2) -> n1 + n2);     
   */    
    @Test
    public void test04() {
        List<Integer> numbers = 
          Arrays.asList(1, 2, 3, 4, 5);        
        int sum = numbers.stream()
                .filter(n -> n % 2  == 1)
                .map(n  -> n * n)
                .reduce(0, Integer::sum);        
        System.out.println(sum);    
    }
    /**     
    *  2.5 有序流与无序流     
    *      流可以是有序的,也可以是
    * 无序的。StreamIntroduction API
    * 可以将表示有序数据源(如列表或排序集)的
    * 有序流转换为无序流。     
    *      我们还可以通过应用排序中间操
    * 作将无序流转换为有序流。     
    */    
    @Test
    public void test05() {
        List<Integer> numbers = Arrays.asList(3,7,9,3,1,2,1, 2, 3, 4, 5);        
        numbers.stream()
                .filter(n -> n % 2  == 1)
                .sorted()
                .forEach(System.out::println);    
    }

}

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接