Steam流的强大作用

1.Stream流的叙述

在认识Stream流之前,我们先来看体会一下Stream流的作用

 代码:

package com.itheima.d2_StreamDemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        Collections.addAll(names,"丹菲","大肥猪","丹菲猪");


//        List<String> zhangList = new ArrayList<>();
//        for (String name: names) {
//            if (name.startsWith("丹"));
//            {
//                zhangList.add(name);
//            }
//        };
//        System.out.println(zhangList);
//
//        List<String> ZhangThreeName = new ArrayList<>();
//        for (String ThreeName1:zhangList ) {
//            if (ThreeName1.length() == 3)
//            {
//                ZhangThreeName.add(ThreeName1);
//            }
//        }
//        System.out.println(ZhangThreeName);

        //使用Stream实现
        names.stream().filter(s -> s.startsWith("丹")).filter(s -> s.length() ==3 ).forEach(s -> System.out.println(s));
    }
}

可以看出在学习Stream流之前,通过集合和数组的API来进行操作,还是相对比较麻烦的,但是引入了Sream流之后,操作就变的非常简便。

Stream流的思想:

 Stream流的作用:简化数组和集合中的API操作。

2.Stream流的获取

 Stream流的获取方式:

 集合获取Stram流分为两种:Map集合获取Stream流和Collection集合获取Stream流,其中值得一提的是Map获取流的方式,分为三种 获取键的流,获取值的流,在之前的文章中讲过还有把键值对当成整体返回获取流。

代码:

package com.itheima.d2_StreamDemo;



import java.util.*;
import java.util.stream.Stream;

public class StreamDemo1 {
    public static void main(String[] args) {
        // -------------- Collection集合获取流
        Collection<String> list = new ArrayList<>();
        Stream<String> s = list.stream();

        //   Map集合获取流  三种 键 值 键值对
        Map<String,Integer> map = new HashMap<>();
        Stream<String> s1 = map.keySet().stream();
        Stream<Integer> s2 = map.values().stream();
        //键值对流 拿整体
        Stream<Map.Entry<String,Integer>> s3 = map.entrySet().stream();
        //数组获取流
        String[] name =  {"丹菲","丹菲猪"};
        Stream<String> nameStream = Arrays.stream(name);
        Stream<String> nameStream1 = Stream.of(name);
    }
}

3.Stream流的常用API

Stream流的API操作就相当于对于数据的分析过程。 在Stream的常用API中分为两类方法,第一种是中间方法也就是在流上的操作,一次操作完毕后还可以继续执行其他操作,而这种方式我们也成为链式编程。 第二种是结束方法,当你使用该方法的时候就不能继续使用其他操作了,也就相当于结束了在流上的操作。

  在这里讲一下filter方法的作用,filter方法相当于过滤的操作,将你想过滤数据的条件通过Lambda表达式写在括号内就可以,参数中写入该接口的实现类,也就是filter中操作的数据类型,只能与你流中的数据类型相同,在代码中是通过Lambda进行了简写。其中 System.out::println 也是简化形式,当你前后操作的变量相同的时候就可以简写成这个样子。

合并流方法注意点:如果两个流的数据类型不是同一数据类型的话,那么当你创建新的流去接收这个流的时候,新的流的数据类型需要是a和b的父类。 

代码:

package com.itheima.d2_StreamDemo;

import com.itheima.d1_unchange_collection.Collection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class StreamDemo2 {
    //常用Api
    /*
    终结方法
    forEach :逐一处理
    count: 统计个数 -long count()
    中间方法
    filter
    limit:取前几个元素
    skip:跳过前几个
    map: 加工
    concat: 合并流
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张三丰");

        // Stream<T> filter(Predicate<? super T> predicate);
//        list.stream().filter(new Predicate<String>() {
//            @Override
//            public boolean test(String s) {
//                 return s.startsWith("张");
//            }
//        }).forEach(System.out::println);

        //简写
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);

        long count = list.stream().filter(s -> s.length() == 3).count();
        System.out.println(count);

        list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(System.out::println);
        System.out.println("-------------");
        list.stream().filter(s -> s.startsWith("张")).skip(2).forEach(System.out::println);

        // Map加工方法
        // 泛型前面为原材料类型  后面为结果类型
//        list.stream().map(new Function<String, String>() {
//            @Override
//            public String apply(String s) {
//                return "黑马的" + s;
//            }
//        });
        list.stream().map(s -> "黑马的" + s).forEach(System.out::println);


        // 把名称加工成对象
//        list.stream().map(new Function<String, Student>() {
//            @Override
//            public Student apply(String s) {
//                return new Student(s);
//            }
//        });
        list.stream().map(s -> new Student(s)).forEach(System.out::println);// 构造器引用 方法引用

        //合并流
        //   public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)  源码拆解
        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        Stream<Integer> s2 = Stream.of(22,23);
        Stream<Object> s3 = Stream.concat(s1,s2);
        //去除重复
        s3.distinct().forEach(System.out::println);

    }
}

过滤方法结果 

 

 

 

包装成所需要字符串结果 

 

包装成对象结果 

 

去除重复结果

 

4.Stream流的综合应用

代码中用到了两个新的API public void  max() 取最大值API和get()API获取当前操作类

在maxAPI中的代码原理其实就是通过实现类(匿名内部类)重写比较器接口中的比较规则来进行排序,可以是升序也可以是降序。想用对象来接收操作类时候,需要注意你在操作方法中返回的类 的类型需要与你对象类型一致。

在代码中静态成员变量的作用是在方法中接收数值,因为foreach方法跟main方法不在同一个方法栈,因此当你在main方法中创建变量的时候,你在该方法中是不可以用的,这个时候就可以用到静态成员变量进行接收,因为是随着类的加载而加载的。

代码:

package com.itheima.d2_StreamDemo;

import java.util.ArrayList;
import java.util.List;

public class StreamDemo3 {
    public static int Allmoney = 0;
    public static int Allmoney2 = 0;
    public static void main(String[] args) {
        List<Employee> one = new ArrayList<>();
        one.add(new Employee("猪八戒","男",30000,25000,null));
        one.add(new Employee("孙悟空","男",25000,1000,"打老板"));
        one.add(new Employee("沙僧","男",20000,2000,null));
        one.add(new Employee("小白龙","男",20000,25000,null));

        List<Employee>  two = new ArrayList<>();
        two.add(new Employee("武松","男",30000,25000,null));
        two.add(new Employee("李逵","男",25000,11000,"打老板"));
        two.add(new Employee("西门庆","男",10000,12000,"偷情"));
        two.add(new Employee("潘金莲","女",210000,125000,"下毒"));

        //找到开发部最高工资员工
        Topperformer tf = one.stream().max((e1,e2 )-> (e1.getSalary() + e1.getBonus())- (e2.getSalary() + e2.getBonus()))
                .map(e -> new Topperformer(e.getName(),e.getSalary()+e.getBonus())).get();
        System.out.println(tf);

        //获取到两个部门的平均工资, 思想:先去除最高和最低工资的员工,拿到中间那批员工对象再去访问他们的属性。
        one.stream().sorted((e1 ,e2) -> (e1.getSalary() +e1.getBonus()) - (e2.getBonus() + e2.getSalary()))
                .skip(1).limit(one.size() -2 ).forEach(e ->{
                    Allmoney += (e.getBonus() +e.getSalary());
                });
        two.stream().sorted((e1 ,e2) -> (e1.getSalary() +e1.getBonus()) - (e2.getBonus() + e2.getSalary()))
                .skip(1).limit(one.size() -2 ).forEach(e ->{
                    Allmoney2 += (e.getBonus() +e.getSalary());
                });

        System.out.println("开发二部平均工资" + Allmoney2 / (one.size() - 2) );
        System.out.println("开发一部的平均工资是" + Allmoney / (one.size()-2 ) );

    }
}

 

5.收集Stream流

为什么要收集Stream流呢? 因为Stream流他是一种对数据操作的过程,但是对于数据的接收我们平时基本上都是使用集合和数组进行接收,因此如果你想用对数据操作过程中的结果的话,就需要回收流,然后将结果存入数组或集合中。

Stream流在回收的时候分为两种API一种是返回集合一种是返回数组。

注意:在返回数组对象的时候,因为泛型不能规定流的数据类型,意思就是在可以通过特殊方法在流中加入其他类型的数据,因此接收数据的数组要为Object类。

 需要注意的一点是,流只能操作一次,也就是说,当你创建的这个流已经回收过了,那么如果你再使用这个流进行操作的话,代码在运行的时候就会进行报错。

代码:

package com.itheima.d2_StreamDemo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDemo4 {
    /*
    流的回收  因为流是一种分析数据的过程,
     而我们平时接受数据是通过集合和数组  因此如果想用流中分析的结果的话,就需要用集合或者数组来回收流
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张三丰");
        Stream<String> s = list.stream().filter(e -> e.startsWith("张"));
       //通过Collectors返回List类型集合
        List<String> list1 = s.collect(Collectors.toList());
        System.out.println(list1);
        //注意:流只能被用一次  如果想用的话需要再创建一个流。
        //List<String> lis2 = s.collect(Collectors.toList());
        //System.out.println(lis2);

        Stream<String> s2 = list.stream().filter(e -> e.startsWith("张"));
        //因为泛型不能规范流中的内容 可以通过其他方法往流中加数据 因此返回值类型要为OBJ
       // Object[] arrs = s2.toArray();
        //那么能不能返回成字符串数组呢?
        //可以的 在参数中 new一个
        String[] arrs= s2.toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.println("数组内容 " + Arrays.toString(arrs));
    }
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值