Stream流详解

Lambda表达式

Stream流往往结合Lambda表达式使用,学习Stream流之前先介绍下Lambda表达式。
作用:简化匿名内部类书写

细节

  • 只能简化函数式接口的匿名内部类写法
  • 函数式接口:有且只有一个抽象方法的接口,可在接口上方加@FunctionalInterface注解做标记

好处

写的代码更加简洁,让我们更加关注于方法体

省略写法

可推导可省略

  • 参数类型可以省略
  • 如果参数只有一个,括号也可以省略不写
  • 如果方法体只有一行,大括号,return,分号都可以省略不写,但还要同时省略
//匿名内部类写法
Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
//Lambda标准写法
Arrays.sort(arr,(Integer o1,Integer o2) ->{
    return o2 - o1;
});
//省略写法
Arrays.sort(arr,(o1,o2) -> o2 - o1);

遍历集合

default修饰符:当没有明确访问修饰符时,默认修饰符为default

默认方法,变量,类,只能在同一个包内被访问

任意集合类型通用

default void forEach(Consumer<? super T> action);
/**
 * 底层原理:
 * forEach方法底层也会遍历集合,并将遍历的结果传给实现Consumer接口的对象中的accept方法
 * 所以直接打印accept方法参数即可
 */
list.forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
        System.out.println(s);
    }
});

Stream流

结合Lambda表达式,用来简化数组,集合的操作

关于对Stream流的理解,可以把他当成工厂中的流水线,每个stream流的操作过程遵循着创建 -->操作 -->获取结果的过程,就像流水线上的节点一样组成一条条线。

使用步骤

  1. 获取Stream流(流水线),并把数据放上去
  2. 使用中间方法对Stream流进行操作
  3. 使用终结方法对Stream流进行操作

获取Stream流

public class Demo0 {
    public static void main(String[] args) {
        //单列集合
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"aaa","bbb","ccc");
        list.stream().forEach(s -> System.out.println(s));

        //双列集合
        //双列集合不能直接获取Stream流,所以须想办法通过单列集合来获取
        HashMap<String,String> map = new HashMap<>();
        map.put("aaa","111");
        map.put("bbb","222");
        map.put("ccc","333");
        //第一种方式:获取键集合
        map.keySet().stream().forEach(s -> System.out.println(map.get(s)));
        //第二种方式:获取键值对集合
        map.entrySet().stream().forEach(entry -> System.out.println(entry));

        //数组
        //使用Arrays中的静态方法stream()
        int[]arr = {2,345,2134,121};
        Arrays.stream(arr).forEach(num -> System.out.println(num));

        //散装的数据
        //使用Stream的静态方法of
        //方法形参是个可变参数,可以传递数组也可以传递零散的数据
        //但只能传递引用数据类型数组,如果传递基本数据类型数组,会将其看做一个整体,放到Stream中
        Stream.of("sfd","sfdsfs","dop").forEach(s -> System.out.println(s));

    }
}

使用中间方法

在这里插入图片描述

细节

  • 修改Stream流中的数据不会对原来的数组或集合造成影响
  • 返回的是一个新的Stream流,原来的Stream流只能使用一次,可使用链式编程
public class Demo1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"aaa","abcd","jfdfs","abh");
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                //返回值为true留下,返回值为false过滤掉
                return s.startsWith("a");
            }
        }).forEach(s -> System.out.println(s));
        list.stream().filter(s -> s.startsWith("a"));
        System.out.println("----------");

        //获取前几个元素
        list.stream().limit(3).forEach(s -> System.out.println(s));
        System.out.println("------------");

        //跳过前几个元素
        list.stream().skip(2).forEach(s -> System.out.println(s));
        System.out.println("---------");

        ArrayList<String> list2 = new ArrayList<>();
        Collections.addAll(list2,"aaa","sss","aaa","fds");
        //元素去重
        //底层用的是HashSet依赖hashSet和equals方法
        list2.stream().distinct().forEach(s -> System.out.println(s));
        System.out.println("-------");

        //将两个流合并成一个
        //尽量保证两个流的数据类型相同,如果不同合并后流的数据类型为两数据类型的共同父类
        Stream.concat(list.stream(),list2.stream()).forEach(s -> System.out.println(s));
        System.out.println("-----------");

        ArrayList<String> list3 = new ArrayList<>();
        Collections.addAll(list3,"a-12","bb-23","yu-89","iu-23");
        //map:转换流中的数据类型
        //第二个泛型和方法的返回值类型是要转换的数据类型
        list3.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s.split("-")[1]);
            }
        }).forEach(num -> System.out.println(num));


        list3.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(num -> System.out.println(num));

    }
}

使用终结方法

在这里插入图片描述

public class Demo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"sd","aaa","sdf","sss");
        //遍历
        list.stream().forEach(s -> System.out.println(s));
        //统计数量
        long count = list.stream().count();
        System.out.println(count);
        System.out.println("-----------");


        //收集流中的数据放到数组中
        Object[] objects = list.stream().toArray();
        System.out.println(Arrays.toString(objects));
        System.out.println("------------");
        //指定数组数据类型
        //泛型为指定类型的数组
        //apply方法参数:流中数据的个数 方法体:创建指定类型数组
        //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));
    }
}
public class Demo3 {
    public static void main(String[] args) {
        String[]arr = {"aaa-111","bbb-222","ccc-333","lll-444","ddd-555"};
        //Collectors.toList():创建集合,collect方法再将流中数据放入集合中
        //Collectors:是Stream流中的工具类
        List<String> list = Arrays.stream(arr).collect(Collectors.toList());
        System.out.println(list);

        Set<String> set = Arrays.stream(arr).collect(Collectors.toSet());
        System.out.println(set);

        /**
         * toMap参数1:键的生成规则
         *           泛型1:流中数据类型
         *           泛型2:键的数据类型
         *
         *           方法形参:流中数据
         *           方法体:处理流中数据生成键的代码
         *           返回值:键
         * toMap参数2:值的生成规则
         *           同理
         *
         * 键不能重复,否则会报异常
         */
        Map<String, Integer> map = Arrays.stream(arr).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("-")[1]);
            }
        }));

        System.out.println(map);


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值