Stream流的简单应用


一、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 +
                '}';
    }
}

Author: xiaoxiao
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source xiaoxiao !
评论
  TOC