Java8新特性之Stream API

  • Stream是Java8中处理集合的关键抽象概念,可以指定希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream来并行执行操作
  • Stream和Collection集合的区别:
    Collection是一种静态的内存数据结构,Stream是有关计算的。
  • 需要注意的三点
    1⃣️Stream自己不会存储数据(所以建立在集合的基础上)
    2⃣️Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream
    3⃣️Stream操作是延迟执行的,他们会等到需要结果的时候再执行

操作Stream的三个步骤

  • 创建Stream:通过数据源(集合、数组)获取一个流
  • 中间操作:中间操作链,对数据源的数据进行处理
  • 终止操作:一旦执行终止操作,就执行中间操作链,并产生结果,之后不会再被使用(延迟执行)

创建Stream

  • 方式一:通过集合
//通过集合创建stream List接口中的默认方法
    @Test
    public void test1(){
        List integers = Arrays.asList(1, 2, 4, 5, 7, 8, 9, 9);

        //default Stream stream():返回一个顺序流
        Stream stream = integers.stream();

        //default Stream parallelStream():返回一个并行流
        Stream parallelStream = integers.parallelStream();

    }
  • 方式二:通过Arrays
    通过Arrays中的静态方法,能够处理对应基本类型的数组生成相应的流(IntStream,LongStream,DoubleStream),也可以生成带泛型的流
//通过数组Arrays中的静态方法
    @Test
    public void test2(){
        int[] arrs = new int[]{1,2,4,5,6,6,7,7};
        IntStream stream = Arrays.stream(arrs);

        String[] names = new String[]{"ssy","cf"};
        Stream stringStream = Arrays.stream(names);
    }
  • 方式三:通过Stream的of()
@Test
    public void test3(){
        Stream stream = Stream.of(1,2,4,5,5,8);
        
    }
  • 方式四:通过Stream创建无限流
@Test
    public void test4(){
        //public static  Stream iterate(T seed, java.util.function.UnaryOperator f)
        Stream.iterate(0,t->t+2).limit(20).forEach(System.out::println);

        //public static  Stream generate(java.util.function.Supplier s)
        Stream.generate(Math::random).limit(20).forEach(System.out::println);

    }

Stream的中间操作

多个中间操作可以链接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”

1、筛选与切片
  • filter(Predicate p)接受Lambda,从流中排除某些元素
  • distinct()筛选,通过流生成元素的hashcode和equals去除重复元素
  • limit(long maxSize)截断流,使元素不超过给定的数量
  • skip(long n)跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流
@Test
    public void test5(){
        List names = Arrays.asList("Tom", "Ssy", "Cf", "Sherry", "Juddy");
        Stream stream = names.stream();
        stream.filter(name -> name.length()<=3).forEach(System.out::println);
        System.out.println("*************");

        //终止操作后不能再操作该stream,需要重新生成
        names.stream().limit(3).forEach(System.out::println);
        System.out.println("**************");

        names.stream().skip(2).forEach(System.out::println);
        System.out.println("****************");


        List names1 = new ArrayList<>(names);//因为asList的结果不能add了
        names1.add("Yu");
        names1.add("Yu");
        names1.add("Yu");
        names1.add("Yu");
        System.out.println(names1.toString());
        names1.stream().distinct().forEach(System.out::println);

    }
2、映射
  • map(Function f) 接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射为一个新的元素
  • flatMap(Function f) 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后将所有流连接成一个流
  • 两者之间的关系类似于下述关系
@Test
    public void test6(){
        List list=new ArrayList(Arrays.asList(1,2,3,4));
        List list1 = Arrays.asList(5,6,7,8);
        list.add(list1);
        System.out.println(list);

        List list2=new ArrayList(Arrays.asList(1,2,3,4));
        list2.addAll(list1);
        System.out.println(list2);

    }
  • 例子
@Test
    public void test7(){
        //map
        List strings = Arrays.asList("aa", "bb", "cc");
        strings.stream().map(String::toUpperCase).forEach(System.out::println);

        //flatMap
        strings.stream().map(StreamTest::fromStringToStream).forEach(System.out::println);
        strings.stream().flatMap(StreamTest::fromStringToStream).forEach(System.out::println);
    }

    public static Stream fromStringToStream(String str){
        char[] strs = str.toCharArray();
        ArrayList arrs = new ArrayList<>();
        for(char c:strs){
            arrs.add(c);
        }
        return arrs.stream();

    }
3、排序
  • 自然排序与定制排序
@Test
    public void test8(){
        //sorted()
        List integers = Arrays.asList(34, 64, 23, 6, 53, 77);
        integers.stream().sorted().forEach(System.out::println);

        //sorted(Comparator com)
        List employees = new ArrayList<>();
        employees.stream().sorted((e1,e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);

    }

Stream的终止操作

终止操作会从流的流水线生成结果,其结果可以是任何不是流的指,例如List、Integer,甚至是void。流进行终止操作后,不能再次使用

1、匹配与查找
  • allMatch(Predicate p) 检查是否匹配所有元素
  • anyMatch(Predicate p) 检查是否至少匹配一个元素
  • noneMatch(Predicate p) 检查是否没有元素匹配
  • findFirst()返回第一个元素
  • findAny() 返回当前流中的任意元素
  • count() 返回流中元素的总个数
  • max(Comparator) 返回流中的最大值
  • min(Comparator)返回流中的最小值
  • forEach(Consumer c)内部迭代
2、规约
  • reduce(T identity, BinaryOperator b)可以将流中的元素反复结合起来,得到一个值,返回T
@Test
    public void  test9(){
        //计算1-10自然数的和
        Integer reduce = Stream.iterate(1, e -> e + 1).limit(10).reduce(0, Integer::sum);
        System.out.println(reduce);
    }
  • reduce(BinaryOperator b)可以将流中的元素反复结合起来,得到一个值,返回 Optional (在optional相关类中再讲)
3、收集
  • collect(Collector c) 将流转换为其他形式,接受一个collector接口的实现,用于给Stream中元素做汇总的方法
  • Collectors实用类,方便地创建常见收集器实例
@Test
    public void test10(){
        List integers = Arrays.asList(34, 64, 23, 6, 53, 77);
        List collect = integers.stream().collect(Collectors.toList());
        collect.forEach(System.out::println);

    }

你可能感兴趣的:(Java8新特性之Stream API)