函数式编程、方法引用、Lambda表达式【总结】

一、Stream流
    1.获取Stream流的方式
        Stream (单列)集合.stream();
        Stream Stream.of(容器);
        注意事项:流对象只能用一次。如果多次使用,需要单独获取流对象
        示例代码:
            public class Demo01GetStream {
                public static void main(String[] args) {
                    //把集合转换为Stream流
                    List<String> list = new ArrayList<>();
                    Stream<String> stream1 = list.stream();

                    Set<String> set = new HashSet<>();
                    Stream<String> stream2 = set.stream();

                    Map<String,String> map = new HashMap<>();
                    //获取键,存储到一个Set集合中
                    Set<String> keySet = map.keySet();
                    Stream<String> stream3 = keySet.stream();

                    //获取值,存储到一个Collection集合中
                    Collection<String> values = map.values();
                    Stream<String> stream4 = values.stream();

                    //获取键值对(键与值的映射关系 entrySet)
                    Set<Map.Entry<String, String>> entries = map.entrySet();
                    Stream<Map.Entry<String, String>> stream5 = entries.stream();

                    //把数组转换为Stream流
                    Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
                    //可变参数可以传递数组
                    Integer[] arr = {1,2,3,4,5};
                    Stream<Integer> stream7 = Stream.of(arr);
                    String[] arr2 = {"a","bb","ccc"};
                    Stream<String> stream8 = Stream.of(arr2);
                }
            }

    2.Stream流的常用方法-forEach
        forEach(Consumer<T>);      用于遍历容器(终结方法)
        示例代码:
            public class Demo02Stream_forEach {
                public static void main(String[] args) {
                    //获取一个Stream流
                    Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
                    //使用Stream流中的方法forEach对Stream流中的数据进行遍历
                    stream.forEach(name->System.out.println(name));

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

                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(5);
                    list.add(4);
                    list.add(3);
                    list.add(2);
                    list.add(1);

                    //获取Stream流
                    Stream<Integer> stream2 = list.stream();
                    //遍历集合
                    stream2.forEach(i -> System.out.println(i));
                }
            }

    3.Stream流的常用方法-filter
        filter(Predicate<t>);           用于过滤条件(延迟方法)
        示例代码:
            public class Demo03Stream_filter {
                public static void main(String[] args) {
                    //创建一个Stream流
                    Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
                    //对Stream流中的元素进行过滤,只要姓张的人
                    Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("张");});
                    //遍历stream2stream2.forEach(name-> System.out.println(name));


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

                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(5);
                    list.add(4);
                    list.add(3);
                    list.add(2);
                    list.add(1);
                    //只要集合中的偶数
                    Stream<Integer> stream3 = list.stream();
                    stream3.filter(num->num % 2 == 0).forEach(i-> System.out.println(i));
                }
            }

    4.Stream流的常用方法-map
        map(Function<T,R>);             用于数据类型转换(延迟方法)
        示例代码:
            public class Demo04Stream_map {
                public static void main(String[] args) {
                    //获取一个String类型的StreamStream<String> stream = Stream.of("1", "2", "3", "4");
                    //使用map方法,把字符串类型的整数,转换(映射)Integer类型的整数
                    Stream<Integer> stream2 = stream.map((String s)->{
                        return Integer.parseInt(s);
                    });
                    //遍历Stream2stream2.forEach(i-> System.out.println(i));

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

                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(5555);
                    list.add(44);
                    list.add(3);
                    list.add(22222);
                    list.add(1111);
                    //通过Stream流完成:1将集合中的数字转成字符串类型的数字。2将字符串类型的数字长度大于3的保存到一个流中。3进行遍历
                    Stream<Integer> stream3 = list.stream();
                    stream3.map(i->i + "").filter(s->s.length() >= 3).forEach(num->System.out.println(num));
                }
            }

    5.Stream流的常用方法-count
        long count();               获取流中的数据个数(终结方法)
        示例代码:
            public class Demo05Stream_count {
                public static void main(String[] args) {
                    //获取一个StreamArrayList<Integer> list = new ArrayList<>();
                    list.add(1);
                    list.add(2);
                    list.add(3);
                    list.add(4);
                    list.add(5);
                    list.add(6);
                    list.add(7);
                    Stream<Integer> stream = list.stream();
                    long count = stream.count();
                    System.out.println(count);//7

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

                    ArrayList<Integer> list2 = new ArrayList<>();
                    list2.add(5555);
                    list2.add(44);
                    list2.add(3);
                    list2.add(22222);
                    list2.add(1111);
                    //通过Stream流完成:1将集合中的数字转成字符串类型的数字。2将字符串类型的数字长度大于3的保存到一个流中。3统计满足条件的元素个数
                    Stream<Integer> stream3 = list2.stream();
                    long count2 = stream3.map(i->i + "").filter(s->s.length() >= 3).count();
                    System.out.println(count2);
                }
            }

    6.Stream流的常用方法-limit
        limit(long num);                截取指定个数的元素(延迟方法)
        示例代码:
            public class Demo06Stream_limit {
                public static void main(String[] args) {
                    //获取一个StreamString[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
                    Stream<String> stream = Stream.of(arr);
                    //使用limitStream流中的元素进行截取,只要前3个元素
                    Stream<String> stream2 = stream.limit(3);
                    //遍历stream2stream2.forEach(name-> System.out.println(name));

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

                    ArrayList<Integer> list2 = new ArrayList<>();
                    list2.add(5555);
                    list2.add(44);
                    list2.add(3);
                    list2.add(22222);
                    list2.add(1111);
                    //通过Stream流完成:1将集合中的数字转成字符串类型的数字。
                    // 2将字符串类型的数字长度大于3的保存到一个流中。3将长度为3的字符串数字只需要保存前两个元素。4遍历
                    Stream<Integer> stream3 = list2.stream();
                    stream3.map(i->i + "").filter(s->s.length() >= 3).limit(2).forEach(s-> System.out.println(s));
                }
            }

    7.Stream流的常用方法-skip
        skip(long num);             跳过指定的元素个数(延迟方法)
        示例代码:
            public class Demo07Stream_skip {
                public static void main(String[] args) {
                    //获取一个StreamString[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
                    Stream<String> stream = Stream.of(arr);
                    //使用skip方法跳过前3个元素
                    Stream<String> stream2 = stream.skip(3);
                    //遍历stream2stream2.forEach(name-> System.out.println(name));

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

                    ArrayList<Integer> list2 = new ArrayList<>();
                    list2.add(5555);
                    list2.add(44);
                    list2.add(3);
                    list2.add(22222);
                    list2.add(1111);
                    //通过Stream流完成:1将集合中的数字转成字符串类型的数字。
                    // 2将字符串类型的数字长度大于3的保存到一个流中。3将长度为3的字符串数字只需要保存前两个元素。
                    // 4将之前保留了前两个元素的流中,跳过第一个。  5遍历
                    Stream<Integer> stream3 = list2.stream();
                    stream3.map(i->i + "").filter(s->s.length() >= 3).limit(2).skip(1).forEach(s-> System.out.println(s));
                }
            }

    8.Stream流的常用方法-concat
        concat(Stream1,Stream2);                将多个流对象拼接(延迟方法)
        示例代码:
            public class Demo08Stream_concat {
                public static void main(String[] args) {
                    //创建一个StreamStream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
                    //获取一个StreamString[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
                    Stream<String> stream2 = Stream.of(arr);
                    //把以上两个流组合为一个流
                    Stream<String> concat = Stream.concat(stream1, stream2);
                    //遍历concatconcat.forEach(name-> System.out.println(name));
                }
            }


    9.集合的案例-传统方式
        略~

    10.集合的案例-Stream流的方式
        public class Demo02StreamTest {
            public static void main(String[] args) {
                //第一支队伍
                ArrayList<String> one = new ArrayList<>();
                one.add("迪丽热巴");
                one.add("宋远桥");
                one.add("苏星河");
                one.add("石破天");
                one.add("石中玉");
                one.add("老子");
                one.add("庄子");
                one.add("洪七公");
                //1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
                //2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
                Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);

                //第二支队伍
                ArrayList<String> two = new ArrayList<>();
                two.add("古力娜扎");
                two.add("张无忌");
                two.add("赵丽颖");
                two.add("张三丰");
                two.add("尼古拉斯赵四");
                two.add("张天爱");
                two.add("张二狗");
                //3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
                //4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
                Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);

                //5. 将两个队伍合并为一个队伍;存储到一个新集合中。
                //6. 根据姓名创建Person对象;存储到一个新集合中。
                //7. 打印整个队伍的Person对象信息。
                Stream.concat(oneStream,twoStream).map(name->new Person(name)).forEach(p-> System.out.println(p));
            }
        }



二、方法引用
    1.使用格式
        调用方法(对象::方法名);
    2.格式解释
        调用方法(需要传递一个对象::一个该对象中的具体方法名);
        等效于:
        重写了抽象方法,在方法体中,去执行传递过来的那个对象中的具体的方法
    3.示例代码:
        public class Demo01Printable {
            //定义一个方法,参数传递Printable接口,对字符串进行打印
            public static void printString(Printable p){
                p.print("HelloWorld");
            }

            public static void main(String[] args) {
                //调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda
                printString((String s)->{
                    System.out.println(s);
                });

                /*
                    分析:
                        Lambda表达式的目的,打印参数传递的字符串
                        把参数s,传递给了System.out对象,调用out对象中的方法println对字符串进行了输出
                        注意:
                            1.System.out对象是已经存在的
                            2.println方法也是已经存在的
                        所以我们可以使用方法引用来优化Lambda表达式
                        可以使用System.out方法直接引用(调用)println方法
                 */
                printString(System.out::println);
            }
        }

    4.对象的方法引用
        public class Demo01ObjectMethodReference {
            //定义一个方法,方法的参数传递Printable接口
            public static void printString(Printable p){
                p.print("Hello");
            }

            public static void main(String[] args) {
                //调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda表达式
                printString((String s)->{
                    //创建MethodRerObject对象
                    MethodRerObject obj = new MethodRerObject();
                    //调用MethodRerObject对象中的成员方法printUpperCaseString,把字符串按照大写输出
                    obj.printUpperCaseString(s);
                });

                /*
                    使用方法引用优化Lambda
                    对象是已经存在的MethodRerObject
                    成员方法也是已经存在的printUpperCaseString
                    所以我们可以使用对象名引用成员方法
                 */
                //创建MethodRerObject对象
                MethodRerObject obj = new MethodRerObject();
                printString(obj::printUpperCaseString);
            }
        }

    5.静态方法引用
        格式:调用方法(类名::方法名);
        示例代码:
            public class Demo01StaticMethodReference {
                //定义一个方法,方法的参数传递要计算绝对值的整数,和函数式接口Calcable
                public static int method(int number,Calcable c){
                   return c.calcAbs(number);
                }

                public static void main(String[] args) {
                    //调用method方法,传递计算绝对值得整数,和Lambda表达式
                    int number = method(-10,(int n)->{
                        //对参数进行绝对值得计算并返回结果
                        return Math.abs(n);
                    });
                    System.out.println(number);

                    /*
                        使用方法引用优化Lambda表达式
                        Math类是存在的
                        abs计算绝对值的静态方法也是已经存在的
                        所以我们可以直接通过类名引用静态方法
                     */
                    int number2 = method(-10,Math::abs);
                    System.out.println(number2);
                }
            }

    6.引用子父类关系的父类方法
        格式:调用方法(super::方法名);
        示例代码:
            public class Man extends Human{
                //子类重写父类sayHello的方法
                @Override
                public void sayHello() {
                    System.out.println("Hello 我是Man!");
                }

                //定义一个方法参数传递Greetable接口
                public void method(Greetable g){
                    g.greet();
                }

                public void show(){
                  /*
                       使用super引用类的成员方法
                       super是已经存在的
                       父类的成员方法sayHello也是已经存在的
                       所以我们可以直接使用super引用父类的成员方法
                   */
                  method(super::sayHello);
                }

                public static void main(String[] args) {
                    new Man().show();
                }
            }

    7.引用本类的方法
        格式:调用方法(this::方法名);
        示例代码:
            public class Husband {
                //定义一个买房子的方法
                public void buyHouse(){
                    System.out.println("北京二环内买一套四合院!");
                }

                //定义一个结婚的方法,参数传递Richable接口
                public void marry(Richable r){
                    r.buy();
                }

                //定义一个非常高兴的方法
                public void soHappy(){
                    //调用结婚的方法,方法的参数Richable是一个函数式接口,传递Lambda表达式
                   /* marry(()->{
                        //使用this.成员方法,调用本类买房子的方法
                        this.buyHouse();
                    });*/

                    /*
                        使用方法引用优化Lambda表达式
                        this是已经存在的
                        本类的成员方法buyHouse也是已经存在的
                        所以我们可以直接使用this引用本类的成员方法buyHouse
                     */
                    marry(this::buyHouse);
                }

                public static void main(String[] args) {
                    new Husband().soHappy();
                }
            }

    8.引用构造方法
        格式:调用方法(对象::new);
        示例代码:
            public class Demo {
                //定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象
                public static void printName(String name,PersonBuilder pb){
                    Person person = pb.builderPerson(name);
                    System.out.println(person.getName());
                }

                public static void main(String[] args) {
                    //调用printName方法,方法的参数PersonBuilder接口是一个函数式接口,可以传递Lambda
                    printName("迪丽热巴",(String name)->{
                        return new Person(name);
                    });

                    /*
                        使用方法引用优化Lambda表达式
                        构造方法new Person(String name) 已知
                        创建对象已知 new
                        就可以使用Person引用new创建对象
                     */
                    printName("古力娜扎",Person::new);//使用Person类的带参构造方法,通过传递的姓名创建对象
                }
            }

    9.引用数组构造方法
        格式:调用方法(数组::new);
        示例代码:
            public class Demo {
                /*
                    定义一个方法
                    方法的参数传递创建数组的长度和ArrayBuilder接口
                    方法内部根据传递的长度使用ArrayBuilder中的方法创建数组并返回
                 */
                public static int[] createArray(int length, ArrayBuilder ab){
                    return  ab.builderArray(length);
                }

                public static void main(String[] args) {
                    //调用createArray方法,传递数组的长度和Lambda表达式
                    int[] arr1 = createArray(10,(len)->{
                        //根据数组的长度,创建数组并返回
                        return new int[len];
                    });
                    System.out.println(arr1.length);//10

                    /*
                        使用方法引用优化Lambda表达式
                        已知创建的就是int[]数组
                        数组的长度也是已知的
                        就可以使用方法引用
                        int[]引用new,根据参数传递的长度来创建数组
                     */
                    int[] arr2 =createArray(10,int[]::new);
                    System.out.println(Arrays.toString(arr2));
                    System.out.println(arr2.length);//10
                }
            }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章