StreamAPI的一些基本用法

StreamAPI的作用

  • Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API(java.util.stream.*)。Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

**注意: **
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

StreamAPI 的执行过程

StreamAPI的一些基本用法_第1张图片

一、创建流

 @Test
    public void test1() {
    
        //可以通过Collection 系列集合提供stream 或parallelStream
        List list = new ArrayList<>();
        Stream stream1 = list.stream();
        
        //可以通过数组
        Integer[] nums = new Integer[10];
        Stream stream2 = Arrays.stream(nums);
        
        //可以通过Stream类中静态方法
        Stream stream3 = Stream.of(1, 2, 3, 4, 5);
        
        //创建无限流
        //迭代
        //limit取前十个
        Stream stream4 = Stream.iterate(0, (x) -> x + 2).limit(10);
        stream4.forEach(System.out::println);
        
        //生成随机数(两个)
        Stream Stream5 = Stream.generate(Math::random).limit(2);
        Stream5.forEach(System.out::println);
    }

二、中间操作

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

  • filter:过滤某些元素
    @Test
    public void test2(){
        //所有的中间操作不会做任何的处理
        Stream stream = emps.stream()
                .filter((e) -> {
                    System.out.println("测试中间操作");
                    return e.getAge() <= 35;
                });

        //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”、“延迟加载”
        stream.forEach(System.out::println);
    }

结果是:只留下年龄<=35的员工
StreamAPI的一些基本用法_第2张图片

 @Test
    public void test2(){
        //所有的中间操作不会做任何的处理
        Stream stream = emps.stream()
                .filter((e) -> {
                    return e.getAge() <= 35;

                }).limit(3);

        //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”、“延迟加载”
        stream.forEach(System.out::println);
    }
  • 结果是:只留下前三个元素

StreamAPI的一些基本用法_第3张图片

  • skip:跳过元素
 @Test
    public void test5(){
        emps.parallelStream()
                .filter((e) -> e.getSalary() >= 5000)
                .skip(2)
                .forEach(System.out::println);
    }

结果是:跳过了前两个
StreamAPI的一些基本用法_第4张图片

  • distinct:去重
 @Test
    public void test6(){
        emps.stream()
                .distinct()
                .forEach(System.out::println);
    }

结果是:将重复的赵六全部去除了[图片上传中…(映射中的Map.png-d90df4-1564816615552-0)]

StreamAPI的一些基本用法_第5张图片

映射:
map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

  • map与flatMap:
    StreamAPI的一些基本用法_第6张图片
    StreamAPI的一些基本用法_第7张图片
@Test
    public void test21(){
        
        List strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");


       
       //map得到,的是一个新流,流中是流流里面是Character
        Stream> stream2 = strList.stream()
                .map(StreamAPITest::filterCharacter);
        
        stream2.forEach((sm) -> {
            sm.forEach(System.out::println);
        });
        
        System.out.println("---------------------------------------------");
        //flatMap:将所有流连接成一个流
        Stream stream3 = strList.stream()
                .flatMap(StreamAPITest::filterCharacter);
        stream3.forEach(System.out::println);
    } 
    
    
    public static Stream filterCharacter(String str){
        List list = new ArrayList<>();
        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }

结果是:效果相同但是,但是遍历逻辑有所不同

StreamAPI的一些基本用法_第8张图片

排序:
sorted()——自然排序
sorted(Comparator com)——定制排序

 @Test
    public void test22(){
        emps.stream()
                .map(Employee::getName)
                .sorted()
                .distinct()
                .forEach(System.out::println);
        System.out.println("------------------------------------");
        emps.stream()
                .sorted((x, y) -> {
                    if(x.getAge() == y.getAge()){
                        return x.getName().compareTo(y.getName());
                    }else{
                        return Integer.compare(x.getAge(), y.getAge());
                    }
                }).distinct()
                .forEach(System.out::println);
    }

终止操作

查找与匹配:
allMatch–检查是否匹配所有元素
anyMatch–检查是否至少匹配一个元素
noneMatch–检查是否没有匹配所有元素
findFirst–返回第一个元素
findAny–返回当前流中的任意元素

  • 测试:
  @Test
    public void test01() {
        //检查是否所有员工状态都是BUSY
        boolean b1 = emps.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
        //检查是否至少有一个员工状态都是BUSY
        boolean b2 = emps.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        //检查是否没有员工状态都是BUSY
        boolean b3 = emps.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b3);

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

        //从大到小排序,取第一个(相当于Max)
        Optional first = emps.stream()
                .sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(first.get());

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


        //串行流,一个一个查,顺序不变,一般是拿的第一个
        Optional any = emps.stream()
                .filter((e1) -> e1.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(any.get());

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

        //并行流,多线程一起查,随机拿符合条件的
        Optional any2 = emps.parallelStream()
                .filter((e1) -> e1.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(any2.get());
    }

结果是:

StreamAPI的一些基本用法_第9张图片

  • 这里需要注意的是,最后两个,单线程和多线程的区别,串行查出来的数据一般是按顺序的,并行就不一定了(赵六顺序再张三后面)

查找与匹配:
count–返回流中元素的总个数
max–返回流中最大值
min–返回流中最小值

 @Test
    public void test02() {
       //计数,员工人数
        long count = emps.stream()
                .count();
        System.out.println(count);

        //按工资取出最大值员工
        Optional max = emps.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(max.get());
        
        //用map取出工资,再用min得到最小工资
        Optional min = emps.stream()
                .map(Employee::getSalary)
                .min(Double::compare);
        System.out.println(min.get());
    }

运行结果:

image.png

归约:
reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
——可以将流中元素反复结合起来,得到一个值。

@Test
    public void test1() {
        List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        //计算和
        //计算结果作为x,再从数组中取出新值作为y,进行下一步计算
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        
        System.out.println(sum);

        System.out.println("----------------------------------------");
       
       //计算总工资
        Optional op = emps.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);

        System.out.println(op.get());
    }

结果是:

StreamAPI的一些基本用法_第10张图片

collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

 @Test
    public void test3() {
        //取名字,封装成list
        List list = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());

        list.forEach(System.out::println);

        System.out.println("----------------------------------");
    
       //取名字,封装成set
        Set set = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());

        set.forEach(System.out::println);

        System.out.println("----------------------------------");
        
        //取名字,封装成hashset
        HashSet hs = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));

        hs.forEach(System.out::println);
    }

结果是:按照各种集合的规则将流封装成各种集合
StreamAPI的一些基本用法_第11张图片

collect是基于Collectors实现的,而Collectors除了上面的to…之外还有

maxBy:最大
minBy:最小
summingDouble:求和
averagingDouble:平均值
counting:计数
summarizingDouble:统计,上面5种都包括
groupingBy:分组(可以自定义分组,可以多级分组)
partitioningBy:分区,将满足条件的分成一个区,不满足的分成一个区
joining:连接字符串,delimiter:分割符,prefix:前缀,suffix:后缀
reducing:归约

你可能感兴趣的:(#,Java基础)