Lambda表达式 函数式接口 Stream流

        
第一章 Lambda表达式

    1.1 Lambda格式:
        标准格式:
        (参数类型  参数名称) -> {代码语句}
        
    格式说明:
        小括号内的语法与传统方法参数列表一致: 无参数则留空; 多个参数用逗号分隔
        -> 是新引入的语法格式, 代表指向动作;
        大括号内的语法与传统方法体要求基本一致;
    
    匿名内部类与Iambda对比:
        new Thread(new Runnable(){
            @Override
            Public void run(){
                System.out.println("多线程任务执行!");
            }
        }).start();
        
        () -> System.out.println("多线程任务执行!");

    Lambda表达式理解为  对某一个接口中的抽象方法的 匿名重写
    前提:
        1. 一定是接口
        2. 接口中有且只有一个抽象方法

    省略格式:
        可推导的就是可省略的
            1. 参数类型可以省略
            2. 如果只有一个参数  ()可以省略
            3. 如果方法体只有一句话  return 大括号  ;  都可以省略
                    但必须是同时省略

第二章 函数式接口
    2.1 概述
        函数式接口在java中是指:有且仅有一个抽象方法的接口
    格式:
        只要确保接口中有且仅有一个抽象方法即可:
        
        修饰符  interface   接口名称{
            public abstract 返回值类型  方法名称(可选参数信息);
            //其他非抽象方法内容
        }
    
    2.2 常用函数式接口
        2.2.1 Supplier接口
        java.util.function.Supplier<T>接口, 它意味着"供给" , 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
            抽象方法 : T get();
        
        代码演示(求数组元素最大值):
          public static void main(String[] args) {

            int[] arr = {3,8,2,5,0};
            method(()->{
                //给数组进行自然排序(即由小到达进行排序)
                Arrays.sort(arr);
                //返回最大索引对应的值 即最大值
                return arr[arr.length-1];
            });
        }
        public static void method(Supplier<Integer> s){
            Integer max = s.get();
            System.out.println(max);
        }    
        
        2.2.2 Consumer接口
        java.util.function.Consumer<T>接口则正好相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型参数决定
            抽象方法:
                void accept(T t);
            默认方法:
                andThen()
            代码演示(使用Consumer接口作为方法的参数将一个字符串转换大小写并打印):
            public static void main(String[] args) {
                //标准格式
                method("Hello world",(String s)->{
                    System.out.println(s.toUpperCase());
                },(String s)->{
                    System.out.println(s.toLowerCase());
                });
                //省略格式
                method("Hello World",s-> System.out.println(s.toLowerCase()),s-> System.out.println(s.toUpperCase()));
            }
            public static void method(String s, Consumer<String> c1, Consumer<String> c2){
                c1.accept(s);
                c2.accept(s);
            //    c1.andThen(c2).accept(s);
            }
        2.2.3 Function接口
            java.util.function.Function<T,R>:接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。有进有出,所以称为“函数Function”。
            抽象方法:
                R apply(T t)
            Function接口中最主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果。
            使用的场景例如:将String类型转换为Integer类型。
            代码演示:
            public static void main(String[] args) {
                //标准格式
                method("100",(String s)->{
                    return Integer.parseInt(s);
                });
                //省略格式
                method("1000",s->Integer.parseInt(s));
                /*
                    方法引用
                        前提  Lambda表达式只有一句话  可能使用
                    类名引用静态方法:
                        类名::方法名
                */
                method("10000",Integer::parseInt);
            }
            public static void method(String num, Function<String, Integer> f){
                Integer n = f.apply(num);
                System.out.println(n);
            }
            代码演示(类名引用构造方法):
            public class Person {
                private String name;
                public Person() {}
                public Person(String name) {this.name = name;}
                public String getName() {return name;}
                public void setName(String name) {this.name = name;}

                @Override
                public String toString() {
                    return "Person{" +
                            "name='" + name + '\'' +
                            '}';
                }
            }
            
            public static void main(String[] args) {
                //标准格式
                method("柳岩",(String name)->{
                    return new Person(name);
                });
                //省略格式
                method("唐嫣",name->new Person(name));
                /*
                    类名引用构造方法
                        类名::new
                */
                method("金莲",Person::new );  //类名引用带参构造
                System.out.println("-----------------------------------");
                method2(Person::new);    //类名引用空参构造
            }
            public static void method(String name, Function<String, Person> f){
                Person p = f.apply(name);
                System.out.println(p);
            }
            public static void method2(Supplier<Person> s){
                Person p = s.get();
                System.out.println(p);
            }
        2.2.4 Predicate接口
            有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用java.util.function.Predicate<T>接口。
            抽象方法:
                boolean  test(T t)   用于条件判断的场景
            默认方法:
                Predicate    and(Predicate p)    并且
                Predicate    or(Predicate p)     或者
                Predicate    nagete()            取反
            代码演示(判断字符串是否以 .java 结尾):
            public static void main(String[] args) {
                //标准格式
                method("HelloWorld.java",(String name)->{
                    return name.toLowerCase().endsWith(".java");
                });
                //省略格式
                method("Hello World.java",s -> s.toLowerCase().endsWith(".java"));
            }
            public static void method(String fileName, Predicate<String> p ){
                boolean test = p.test(fileName);
                System.out.println(test);
            }
            //判断字符串是否包含H W 
            public static void main(String[] args) {
                //标准格式
                method1("Hello World", (String s) -> {
                    return s.contains("H");
                }, (String s) -> {
                    return s.contains("W");
                });
                //省略格式
                method1("Hello World", s -> s.contains("H"), s -> s.contains("W"));
            }
            public static void method1(String s, Predicate<String> p1, Predicate<String> p2) {
//               boolean b1 = p1.test(s);
//                boolean b2 = p2.test(s);
//                if (b1 && b2) {
//                    System.out.println("既包含H又包含W");
//                }

                boolean b = p1.and(p2).test(s);
                if (b){
                    System.out.println("既包含H又包含W");
                }
            }

第四章 Stream流
    4.1 获取流方式
        java.util.stream.Stream接口
            获取Stream流对象
                1. Collection接口 
                    Public default Stream stream()
                
                2. Stream接口静态方法
                    static Stream of(T...t);
    4.2 常用方法
        终结方法(只能调用一次):  返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似`StringBuilder`那样的链式调用。
                    本小节中,终结方法包括 count 和 forEach 方法
            long count(); 统计个数
            void forEach(Consumer action);  逐一处理
        非终结方法:  返回值类型仍然是`Stream`接口自身类型的方法,因此支持链式调用
            Stream<T> limit(long maxSize):获取Stream流对象中的前n个元素,返回一个新的Stream流对象
            Stream<T> skip(long n): 跳过Stream流对象中的前n个元素,返回一个新的Stream流对象
            Stream<T> distinct();  去重
            Stream<T> filter(Predicate<? super T> predicate); 过滤  可以通过`filter`方法将一个流转换成另一个子集流
            <R> Stream<R> map(Function<? super T, ? extends R> mapper);  映射 该接口需要一个 Function函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
        静态方法:
            Stream concat(Stream s1, Stream s2)  组合(将两个流合并成一个新的流)
        
        代码演示:
        public static void main(String[] args) {
            Stream<String> stream =  Stream.of("大娃","二娃","三娃","四娃","五娃","六娃","七娃","爷爷","蛇精","蝎子精","蛇精","蝎子精");

            //统计个数
            long count = stream.count();
            System.out.println(count);

            //逐一处理(类似于遍历)
            stream.forEach(System.out::println);

            //获取前8个 跳过前7个 将第8个单独输出
            stream.limit(8).skip(7).forEach(System.out::println);
            //跳过前7个, 获取剩余的第一个元素  再将元素输出
            stream.skip(7).limit(1).forEach(System.out::println);

            //去重
            stream.distinct().forEach(System.out::println);

            //过滤   筛选
            stream.filter(s->s.contains("精")).forEach(System.out::println);

            //映射   将一种类型转换成另一种类型
            Stream<Person> personStream = stream.map(Person::new);
            personStream.forEach(System.out::println);

            //组合 拼接
            Stream<String> s2 = Stream.of("1", "2", "3");
            Stream.concat(stream,s2).forEach(System.out::println);
    }

        Stream综合案例
        
        现在有两个`ArrayList`集合存储队伍当中的多个成员姓名,要求使用传统的Stream流方式,进行以下若干操作步骤:

            1. 第一个队伍只要名字为3个字的成员姓名;
            2. 第一个队伍筛选之后只要前3个人;
            3. 第二个队伍只要姓张的成员姓名;
            4. 第二个队伍筛选之后不要前2个人;
            5. 将两个队伍合并为一个队伍;
            6. 打印整个队伍的姓名信息。
        代码演示:
        import java.util.ArrayList;
        import java.util.List;
        import java.util.stream.Stream;

        public class lianXi {
            public static void main(String[] args) {
                List<String> one = new ArrayList<>();
                one.add("迪丽热巴");
                one.add("宋远桥");
                one.add("苏星河");
                one.add("老子");
                one.add("庄子");
                one.add("孙子");
                one.add("洪七公");

                List<String> two = new ArrayList<>();
                two.add("古力娜扎");
                two.add("张无忌");
                two.add("张三丰");
                two.add("赵丽颖");
                two.add("张二狗");
                two.add("张天爱");
                two.add("张三");

                // 1. 第一个队伍只要名字为3个字的成员姓名;
                Stream<String> stream = one.stream().filter(s -> s.length() == 3);

//                2. 第一个队伍筛选之后只要前3个人;
//                3. 第二个队伍只要姓张的成员姓名;
                //two.stream().filter(s->s.startsWith("张")).forEach(System.out::println);
//                4. 第二个队伍筛选之后不要前2个人;
                Stream<String> to2 = two.stream().filter(s -> s.startsWith("张")).skip(2);

//                5. 将两个队伍合并为一个队伍;
//                6. 打印整个队伍的姓名信息。
                Stream.concat(stream, to2).forEach(System.out::println);
            }
        }    
        结果:
        宋远桥
        苏星河
        洪七公
        张二狗
        张天爱
        张三

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值