一、为什么需要用Stream?
Java8 中的Stream API 它与Java.io包里的InputStream 和 OutputStream 是完全不同的概念,也不同于StAX对XML解析的Stream。
它提供了一种高效且易于使用的处理数据的方式,是对集合(Collection)对象功能的增强。
它可以指定对集合的操作,可以执行非常复杂的查找、过滤、映射数据等操作。
使用Stream API 对集合数据进行操作,就类似于SQL执行的数据查询。也可以使用Stream API 来并行执行操作。

二、什么是Stream?
流(Stream)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。集合讲的是数据,流讲的是计算。
注意:
①Stream 自己不会存储元素;
②Stream 返回一个新结果的数据Stream,而对源对象不会产生影响;
③Stream 操作是延迟执行的,这意味着它会等到需要结果的时候 才全部执行,
(中间操作:不会进行任何操作;终止操作:一次性执行全部内容,即“惰性求值”)

三、如何操作Stream?

java和钉钉Stream代码_System


Java8中的Collection接口被扩展,提供了两个获取流的方法:

* default Stream<E> stream()   返回一个顺序流
* default Stream<E> parallelStream() 返回一个并行流

1、 创建 Stream

//创建Stream
     @Test
     public void test1(){
          //1. 可以通过 Collection 系列集合提供的 Stream() 或 parallelStream()
          List<String> list = new ArrayList<>();
          Stream<String> stream1 = list.stream();

          //2、通过Arrays 中的静态方法 stream()获取数组流
          Employee[] emps = new Employee[10];
          Stream<Employee> stream2 = Arrays.stream(emps);

          //3.通过Stream类中的静态方法of()
          Stream<String> stream3 = Stream.of("aa", "bb", "cc");

          //4.创建无线流
          //迭代
          Stream<Integer> stream4 = Stream.iterate(0, (e) -> e+2);
          stream4.limit(10).forEach(System.out::println);

          System.out.println("====================");

          //生成
          Stream.generate(() -> (int)(Math.random() * 100)).limit(5).forEach(System.out::println);

     }

2、 中间操作
筛选与切片
filter —— 接收Lambda,从流中排除某些元素;
limit —— 截断流,使其元素不超过给定数量;
skip(n) —— 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit互补。
distinct —— 筛选,通过流所生成元素的hasCode() 和 equals() 去除重复元素

@Test
     public void test1(){
          //中间操作: 不会执行任何操作
          Stream<Employee> stream = emp.stream()
                                        .filter((e) -> {
                                            System.out.println("Stream API的中间操作");
                                            return e.getAge() > 35;
                                        });

          //终止操作: 一次性执行全部内容,即“惰性求值”
          stream.forEach(System.out::println);
     }

     @Test
     public void test2(){
          emp.stream().filter((e) -> {
              System.out.println("短路!");
              return e.getSalary() < 4000;
          }).limit(2).forEach(System.out::println);
     }

     @Test
     public void test3(){
          emp.stream().filter((e) -> {
              System.out.println("短路!");
              return e.getSalary() > 3000;
          }).skip(2).distinct().forEach(System.out::println);
     }

3、映射 map——接收一个lambda表达式,将元素映射成其他元素或提取信息。接收一个函数作为参数 ,该函数会被每个元素应用,并将其映射成一个新元素。
flatMap——接收一个函数作为参数,将流中每个值都换成另外一个流,然后把所有流连接成一个流。

@Test
     public void test4(){
          List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
          list.stream()
              .map((str) -> str.toUpperCase())
              .forEach(System.out::println);
          System.out.println("-------------------");

          emp.stream()
              .map(Employee::getName)
              .forEach(System.out::println);

          System.out.println("--------------------------------------------");

          Stream<Stream<Character>> stream  =  list.stream().map(StreamTest2::filterChar);  //每个map都会映射成一个Stream
          stream.forEach((sm) -> {
              sm.forEach(System.out::println);
          });

          System.out.println("-------------------");

          Stream<Character> stream2 = list.stream().flatMap(StreamTest2::filterChar);
          stream2.forEach(System.out::println);
     }

     public static Stream<Character> filterChar(String str){
          List<Character> list = new ArrayList<>();
          for (Character ch : str.toCharArray()) {
              list.add(ch);
          }

          return list.stream();
     }

4、排序 sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator com) 产生一个新流,其中按比较器自定顺序排序

@Test
     public void test5(){
          List<String> list = Arrays.asList("ccc", "aaa", "bbb", "eee", "ddd");
          list.stream()
              .sorted()
              .forEach(System.out::println);
          System.out.println("--------------------");

          emp.stream()
              .sorted((e1, e2) -> {
                   if (e1.getAge() == e2.getAge()) {
                        return e1.getName().compareTo(e2.getName());
                   }else{
                        return e1.getAge().compareTo(e2.getAge());
                   }
              }).forEach(System.out::println);
     }