一、stream流的使用步骤
1、先得到一条Stream流,并把数据放上去
2、使用中间方法对流水线上的数据进行操作
3、使用终结方法对流水线上的数据进行操作
二、获取stream流
| 获取方式 | 方法名 | 说明 | 
|---|---|---|
| 单列集合 | default Stream< E> stream() | Collection中的默认方法 | 
| 双列集合 | 无 | 无法直接使用stream流 | 
| 数组 | public static < T> Stream< T> stream(T[] array) | Arrays工具类中的静态方法 | 
| 一堆零散数据 | public static < T> Stream< T> of(T…values) | Stream接口中的静态方法 | 
2.1 单列集合获取Stream流
// 1.单列集合获取Stream流
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "a","b","c","d","e");
    /*    // 获取到一条流水线,并把集合中的数据放到流水线上
        Stream<String> stream1 = list.stream();
        // 使用终结方法打印一下流水线上的所有数据
        stream1.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
     */
        list.stream().forEach(s -> System.out.println(s));
2.2 双列集合获取Stream流
    public static void main(String[] args) {
        // 双列集合 ---> 无法直接使用stream流
        // 1.创建双列集合
        HashMap<String, Integer> hashMap = new HashMap<>();
        // 2.添加数据
        hashMap.put("aaa", 111);
        hashMap.put("bbb", 222);
        hashMap.put("ccc", 333);
        hashMap.put("ddd", 444);
        // 3.第一种方式获取stream流
        hashMap.keySet().stream().forEach(s -> System.out.println(s));
        // 4.第二种方式获取stream流
        hashMap.entrySet().stream().forEach(s -> System.out.println(s));
    }
2.3 数组获取Stream流
    public static void main(String[] args) {
        // 数组
        // 1.创建数组
        int[] arr = {1,2,3,4,5,6,7,8,9,10};
        String[] arr2 = {"a", "b", "c", "d", "e", "f"};
        // 2.获取stream流
        Arrays.stream(arr).forEach(s-> System.out.println(s));
        System.out.println("****************");
        Arrays.stream(arr2).forEach(s-> System.out.println(s));
        System.out.println("****************");
        // 注意:
        // stream接口中静态方法of的细节:
        // 方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组
        // 但是数组必须是引用类型的,如果传递基本数据类型,是会把整个数组当成一个元素,放到Stream流中
        Stream.of(arr).forEach(s-> System.out.println(s));  // [I@448139f0
    }
2.4 一堆零散数据获取Stream流
    public static void main(String[] args) {
        // 一堆零散数据
        Stream.of(1,2,3,4).forEach(s-> System.out.println(s));
        System.out.println("**********************");
        Stream.of("a", "b", "c", "d", "e", "f").forEach(s-> System.out.println(s));
    }
三、stream流的中间方法
| 名称 | 说明 | 
|---|---|
| Stream< T> filter(Predicate<? super T> predicate) | 过滤 | 
| Stream< T> limit(long maxSize) | 获取前几个元素 | 
| Stream< T> skip(long n) | 跳过前几个元素 | 
| Stream< T> distinct() | 元素去重,依赖(hashCode和equals方法) | 
| static < T> Stream< T> concat(Stream a, Stream b) | 合并a和b两个流为一个流 | 
| Stream< R> map (Function< T, R> mapper) | 转换流中的数据类型 | 
注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,所以一般建议使用链式编程。
注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据。
3.1 filter、limit、skip方法
    public static void main(String[] args) {
        /*
            filter            过滤
            limit             获取前几个元素
            skip              跳过前几个元素
            注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,所以一般建议使用链式编程。
            注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据。
         */
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        // filter 过滤   把张开头的留下,其余的过滤掉
        /*
        // 匿名内部类
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                // 如果返回值为true,表示当前数据留下
                // 如果返回值是false,表示当前数据舍弃不要
                return s.startsWith("张");
            }
        }).forEach(s -> System.out.println(s));
        */
        // lambda表达式
        // list.stream().filter(s->s.startsWith("张")).forEach(s -> System.out.println(s));
        // limit  获取前几个元素
        // list.stream().limit(3).forEach(s -> System.out.println(s));
        // skip 跳过前几个元素
        // list.stream().skip(4).forEach(s -> System.out.println(s));
        // 获取 "张强","张三丰","张翠山"
        // list.stream().skip(3).limit(3).forEach(s -> System.out.println(s));
        list.stream().limit(6).skip(3).forEach(s -> System.out.println(s));
    }
3.2 distinct、concat方法
    public static void main(String[] args) {
        /*
            distinct         元素去重,依赖(hashCode和equals方法)
            concat           合并a和b两个流为一个流
            注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,所以一般建议使用链式编程。
            注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据。
         */
        ArrayList<String> list1 = new ArrayList<String>();
        Collections.addAll(list1, "张无忌","张无忌","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        ArrayList<String> list2 = new ArrayList<String>();
        Collections.addAll(list2, "周芷若","赵敏");
        // distinct         元素去重,依赖(hashCode和equals方法)
        // list1.stream().distinct().forEach(s -> System.out.println(s));
        // concat           合并a和b两个流为一个流
        Stream.concat(list1.stream(), list2.stream()).forEach(s -> System.out.println(s));
    }
3.3 map方法
    public static void main(String[] args) {
        /*
            map           转换流中的数据类型
            注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,所以一般建议使用链式编程。
            注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据。
         */
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "张无忌-15","周芷若-14","赵敏-13","张强-20","张三丰-100","张翠山-40","张良-35","王二麻子-37","谢广坤-41");
        // 只获取里面的年龄并进行打印
        // String ---> int
        // 第一个类型:流中原本的数据类型
        // 第二个类型:表示转换之后的数据
        // apply的形参s:依次表示流里面的每一个数据
        // 返回值:表示转换之后的数据
        list.stream().map(new Function<String, Object>() {
            @Override
            public Object apply(String s) {
                String[] arr = s.split("-");
                String ageString = arr[1];
                int age = Integer.parseInt(ageString);
                return age;
            }
        }).forEach(s-> System.out.println(s));
        System.out.println("******************");
        list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));
    }
四、stream流中的终结方法
| 名称 | 说明 | 
|---|---|
| void forEach(Consumer action) | 遍历 | 
| long count() | 统计 | 
| toArray() | 收集流中的数据,放到数组中 | 
| collect(Collector collector) | 收集流中的数据,放到集合中 | 
4.1 void forEach(Consumer action)、long count()、toArray()方法
    public static void main(String[] args) {
        /*
            void forEach(Consumer action)      遍历
            long count()                       统计
            toArray()                          收集流中的数据,放到数组中
         */
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤");
        // void forEach(Consumer action)      遍历
        // Consumer的泛型:表示流中的数据的类型
        // accept()方法的形参s:依次表示流里面的每一个数据
        // 方法体:对每一个数据进行处理操作
    /*    list.stream().forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
     */
        list.stream().forEach(s -> System.out.println(s));
        System.out.println("*******long count()**********");
        // long count()     统计
        long count = list.stream().count();
        System.out.println("count: " + count);
        System.out.println("********toArray()*********");
        // toArray() 收集流中的数据,放到数组中
        Object[] arr1 = list.stream().toArray();
        System.out.println(Arrays.toString(arr1));
        System.out.println("*********toArray()********");
        // IntFunction的泛型:具体类型的数组
        // apply()的形参:流中数据的个数,要和数组的长度保持一致
        // apply()的返回值:具体类型的数组
        // 方法体:就是创建数组
        // toArray()方法的参数的作用:负责创建一个指定类型的数组
        // toArray()方法的底层,会依次得到流里面的每一个数据,并把数据放到数组里
        // toArray()方法的返回值:是一个装着流里面所有数据的数组
        /*String[] arr = list.stream().toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.println(Arrays.toString(arr));*/
        String[] arr2 = list.stream().toArray(value -> new String[value]);
        System.out.println(Arrays.toString(arr2));
    }
4.2 collect(Collector collector)方法
    public static void main(String[] args) {
        /*
            collect(Collector collector)  收集流中的数据,放到集合中
         */
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "张无忌-男-15","周芷若-女-14","赵敏-女-13","张强-男-20","张三丰-男-100","张翠山-男-40","张良-男-35","王二麻子-男-37","谢广坤-男-41");
        System.out.println("******** List *******");
        // 收集到List集合中
        // 需求:
        // 要把所有的男性收集起来
        List<String> newList = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toList());
        System.out.println(newList);
        System.out.println("********* Set **********");
        // 收集到Set集合中
        // 需求:
        // 要把所有的男性收集起来
        Set<String> newSet = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toSet());
        System.out.println(newSet);
        System.out.println("********** Map *********");
        // 收集到Set集合中
        // 需求:
        // 要把所有的男性收集起来
        // 键:姓名,  值:年龄
        /*
            toMap: 参数一表示键的生成规则
                   参数二表示值的生成规则
            参数一:
                Function泛型一:表示流中每一个数据的类型
                        泛型二:表示Map集合中键的数据类型
                方法apply形参:依次表示流里面的每一个数据
                       方法体:生成键的代码
                       返回值:已经生成的键
            参数二:
                Function泛型一:表示流中每一个数据的类型
                        泛型二:表示Map集合中值的数据类型
                方法apply形参:依次表示流里面的每一个数据
                       方法体:生成值的代码
                       返回值:已经生成的值
            保存到Map集合中,键不能重复
         */
        /*Map<String, Integer> newMap = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toMap(new Function<String, String>() {
                    @Override
                    public String apply(String s) {
                        return s.split("-")[0];
                    }
                }, new Function<String, Integer>() {
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s.split("-")[2]);
                    }
                }));
        System.out.println(newMap);*/
        Map<String, Integer> newMap = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2])));
        System.out.println(newMap);
    }
五、练习
5.1 练习一
定义一个集合,并添加一些整数 1,2,3,4,5,6,7,8,9,10
过滤奇数,只留下整数
并将结果保存起来
    public static void main(String[] args) {
        /*
            定义一个集合,并添加一些整数   1,2,3,4,5,6,7,8,9,10
            过滤奇数,只留下整数
            并将结果保存起来
         */
        ArrayList<Integer> list = new ArrayList<Integer>();
        Collections.addAll(list, 1,2,3,4,5,6,7,8,9,10);
        List<Integer> newList = list.stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println(newList);
    }
5.2 练习二
创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄
“zhangsan,23”
“lisi,24”
“wangwu,25”
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
    public static void main(String[] args) {
        /*
            创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄
            "zhangsan,23"
            "lisi,24"
            "wangwu,25"
            保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
         */
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "zhangsan,23", "lisi,24","wangwu,25");
        Map<String, Integer> newMap = list.stream()
                .filter(s -> Integer.parseInt(s.split(",")[1]) >= 24)
                .collect(Collectors.toMap(
                        s -> s.split(",")[0],
                        s -> Integer.parseInt(s.split(",")[1])));
        System.out.println(newMap);
    }
5.3 练习三
现在有两个ArrayList集合,
第一个集合中:存储6名男演员的名字和年龄。第二个集合中:存储6名女演员的名字和年龄。
姓名和年龄中间用逗号隔开。比如:张三,23
要求完成以下操作:
1,男演员只要名字为3个字的前两人
2,女演员只要姓杨的,并且不要第一个
3,把过滤后的男演员姓名和女演员姓名合并到一起
4,将上一步的演员信息封装成Actor对象。
5,将所有的演员对象都保存到List集合中男演员:”蔡虚坤,24”,”叶憨咸,23”,”刘不甜,22”,”吴签,24”,”谷嘉,30”,”肖梁梁,27”
女演员:”赵小怡,35”,”杨依,36”,”高苑苑,43”,”张甜甜,31”,”刘诗,35”,”杨小幂,33”
    public static void main(String[] args) {
        /*
            现在有两个ArrayList集合,
            第一个集合中:存储6名男演员的名字和年龄。第二个集合中:存储6名女演员的名字和年龄。
            姓名和年龄中间用逗号隔开。比如:张三,23
            要求完成以下操作:
            1,男演员只要名字为3个字的前两人
            2,女演员只要姓杨的,并且不要第一个
            3,把过滤后的男演员姓名和女演员姓名合并到一起
            4,将上一步的演员信息封装成Actor对象。
            5,将所有的演员对象都保存到List集合中
            男演员:"蔡虚坤,24","叶憨咸,23","刘不甜,22","吴签,24","谷嘉,30","肖梁梁,27"
            女演员:"赵小怡,35","杨依,36","高苑苑,43","张甜甜,31","刘诗,35","杨小幂,33"
         */
        ArrayList<String> list1 = new ArrayList<String>();
        Collections.addAll(list1, "蔡虚坤,24","叶憨咸,23","刘不甜,22","吴签,24","谷嘉,30","肖梁梁,27");
        ArrayList<String> list2 = new ArrayList<String>();
        Collections.addAll(list2, "赵小怡,35","杨依,36","高苑苑,43","张甜甜,31","刘诗,35","杨小幂,33");
        Stream<String> stream1 = list1.stream()
                .filter(s -> s.split(",")[0].length() == 3)
                .limit(2);
        Stream<String> stream2 = list2.stream()
                .filter(s -> s.startsWith("杨"))
                .skip(1);
        List<Actor> newList = Stream.concat(stream1, stream2)
                .map(s -> new Actor(
                        s.split(",")[0],
                        Integer.parseInt(s.split(",")[1])))
                .collect(Collectors.toList());
        System.out.println(newList);
    }
类 Actor
public class Actor {
    String name;
    Integer age;
    public Actor(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Actor{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
 
                     
                     
                        
                        