Lambda表达式,JDK1.8的新技术

Lambda表达式

        就是函数式编程是Java的新技术,是一种新的设计思想,目的是为了简化代码!!, 面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做:要干嘛就干嘛!!就是为了可以简化代码!

  

Lambda表达式的简化格式(重点):(形参列表) ->  { //被简化的匿名内部类对象中,重写方法的方法体代码 }

    格式解析: (形参列表):与被重写方法的形参列表一模一样。 -> 是一个新语法,无实现含义,只是指向重写方法的方法体代码。
       {} 被简化的匿名内部类对象中,重写方法的方法体代码

         Lambda表达式简化Runnable接口的匿名内部类写法。 点进Runnable接口中去,发现只有一个抽象方法、

 并且有 @FunctionalInterface (函数式接口的注解)。有了这个注解的接口就是函数式接口,这个接口有且仅有一个抽象方法。

举例子:

public class LambdaDemo04 {
    public static void main(String[] args) {
        List<Student> stus = new ArrayList<>();
        stus.add(new Student("白文波",21,"101期"));
        stus.add(new Student("李涛涛",23,"97期"));
        stus.add(new Student("常浩",18,"97期"));
        System.out.println(stus);
        // 按照年龄由小到大排序。
     /*   Collections.sort(stus, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        });*/

        // Lambda表达式简化函数式接口的匿名内部类写法
        Collections.sort(stus, (Student o1, Student o2) ->{
            return o1.getAge() - o2.getAge();
        });

        Collections.sort(stus, ( o1,  o2) ->{
            return o1.getAge() - o2.getAge();
        });

        Collections.sort(stus, ( o1,  o2) -> o1.getAge() - o2.getAge() );



        System.out.println(stus);
    }
}

常见的函数式接口有以下

supplier接口:函数式接口。 生产结果数据返回:生产者接口。

public class SupplierDemo01 {
    public static void main(String[] args) {
       /* Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "欢迎徐干";
            }
        };
        // 简化代码
        Supplier<String> supplier1 = () -> "欢迎徐干";
        System.out.println(supplier1.get());*/

      /*  add(new Supplier<String>() {
            @Override
            public String get() {
                return "李四";
            }
        }, new Supplier<String>() {
            @Override
            public String get() {
                return "王五";
            }
        });
*/
        add(()->"李四" , ()->"王五");

        //add(()->"徐干" , ()->"白文波");
    }

    public static void add(Supplier<String> p1 , Supplier<String> p2){
        System.out.println(p1.get() + "=>" + p2.get());
    }
}
public class SupplierExecDemo02 {

    public static void main(String[] args) {
        //(2)创建一个Supplier对象生产一个最大值传给printMax方法。
      /*  printMax(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int[] arrs = new int[]{100,23,999,2};
                // 求出数组的最大值。
                int max = arrs[0];
                for(int ele : arrs){
                    if(ele > max){
                        max = ele;
                    }
                }
                return max; // 提供最大值
            }
        });*/

        printMax(() -> {
            int[] arrs = new int[]{100,23,999,2};
            // 求出数组的最大值。
            int max = arrs[0];
            for(int ele : arrs){
                if(ele > max){
                    max = ele;
                }
            }
            return max; // 提供最大值
        });
    }

    //(1)先定义一个方法去获取数组的最大值。
    public static void printMax(Supplier<Integer> p1){
        int max = p1.get() ; // 取出最大值
        System.out.println("最大值输出:"+max);
    }
}

Consumer接口:是用来消费数据的,根Supplier是相反的。

下列展示3个例子

public class ConsumerDemo01 {
    public static void main(String[] args) {

//注释
      /*  Consumer<String> c = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s.toUpperCase());
            }
        } ;
        c.accept("itheima");*/



        conYouData(s -> System.out.println(s.toUpperCase()),"itheima");
        conYouData(s -> System.out.println(s.toLowerCase()),"itheimaABCD");
        conYouData(s -> System.out.println(s.length()),"itheimaABCD");
    }

    public static void conYouData(Consumer<String> p1 ,String data){
        p1.accept(data);
    }

}
Consumer中的抽象方法:
    void accept(T t):用来接收数据,消费数据的。
    andThen:消费完一个数据以后然后继续消费。

  andThen使用需求:
      需求: 我给你一个字符串,请先以大写的形式输出,然后以小写的形式输出。
*/
public class ConsumerDemo02 {
    public static void main(String[] args) {
        printStr(s -> System.out.println(s.toUpperCase()) ,
                 s -> System.out.println(s.toLowerCase()) ,
                 "HelloWord");
    }

    public static void printStr(Consumer<String> p1 , Consumer<String> p2 , String data){
        /**
         *  default Consumer<T> andThen(Consumer<? super T> after) {
                    return (T t) -> {
                              this.accept(t); // p1.accept(HelloWord);
                              after.accept(t);// p2.accept(HelloWord);
                     };
           }
         *
         * */
        p1.andThen(p2).accept(data);
    }
}
public class ExecDemo03 {
    public static void main(String[] args) {
        String[] arrs = {"古力娜扎,女" , "迪丽热巴,女" , "马尔扎哈,男"};
        Consumer<String> p1 = s -> System.out.print(s.split(",")[0]+"=");
        Consumer<String> p2 = s -> System.out.println(s.split(",")[1]);
        forEach(arrs ,p1 , p2 );
    }

    // 写一个方法负责,接收数据
    public static void forEach(String[] datas, Consumer<String> p1, Consumer<String> p2){
        for(String data : datas){
            // data : 古力娜扎,女
            p1.andThen(p2).accept(data);
        }
    }
}
输出结果:

古力娜扎=女

迪丽热巴=女

马尔咋哈=男

Function: 功能接口,工厂接口:你给我原材料,我生产结果给你。

下列展示2个例子

public class FuncationDemo01 {
    public static void main(String[] args) {
        // 需求:请帮我把"23",乘以二倍返回。
        /*

        Function<String , Integer> f1 = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return 2 * Integer.valueOf(s);
            }
        };

        */
        Function<String , Integer> f1 = s -> 2 * Integer.valueOf(s);
        System.out.println(f1.apply("23"));
    }
}
抽象方法:
     R apply(T t);
     T:原材料的数据类型
     R:结果数据的类型
 默认方法:
     andThen:完成功能以后然后继续完成另一个功能。
              重点:把第一个功能的结果作为第二个功能的原材料。
     需求:我现在给你一个字符串数字“23”,希望先转成整数*2,接下来输出“结果是46”


 */
public class FuncationDemo02 {
    public static void main(String[] args) {
        // 功能1:把字符串转成整数*2
        // 原材料是字符串,结果是整数,
        Function<String , Integer> p1 = s -> 2 * Integer.valueOf(s); // "23"-> 46
        // 功能2:功能1的结果46传输给功能2 , 把整数的结果46输出成“结果是46”
        // 原材料是Integer,结果是字符串。
        Function<Integer,String> p2 = s -> "和是:"+s; // 46 -> "和是46"
        // 功能3 :把“和是46”转换成“黑马输出了和是46”
        // 原材料是字符串,结果是字符串。
        Function<String,String> p3 = s -> "黑马输出了"+s; // "和是46" -> 黑马输出了和是46

        fun(p1 , p2 , p3, "23");
    }

    public static void fun(Function<String , Integer> p1 ,
                            Function<Integer,String> p2 ,
                           Function<String,String> p3,
                           String data){
        /**
         *  default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
                return (T t) -> after.apply(apply(t));
                             // p2.apply(p1.apply("23"));
            }
         *
         * */
        String rs  = p1.andThen(p2).andThen(p3).apply(data);
        System.out.println(rs);
    }
}

Predicate接口: 条件判断有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用

下列展示4个例子

抽象方法:
         boolean test(T t);
         给一个数据返回真或者假。
 */
public class PredicateDemo01 {
    public static void main(String[] args) {
       /* Predicate<String> p1 = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length() >= 6;// 校验密码
            }
        };*/

        Predicate<String> p1 = s -> s.length() >= 6 ;
        System.out.println(p1.test("admin123"));
    }
}
Predicate接口的默认方法:
 *     可以实现条件中的 与&& 或|| 非! 判断。
 *     通过默认方法去实现的。
 * 默认方法:
 *    and:实现与关系条件判断。
 *      default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) && other.test(t);
        }
    需求:
        判断某个名字是否以张开始,并且长度是否>2.
    分析:两个条件。
 *
 * */
public class PredicateDemo02 {
    public static void main(String[] args) {
        checkName(s -> s.startsWith("张"), s -> s.length() > 2, "张三丰");
    }

    public static void checkName(Predicate<String> p1 , Predicate<String> p2
            , String name){
        /**
         *  default Predicate<T> and(Predicate<? super T> other) {
                 return (t) -> this.test(t) && other.test(t);
                        //     p1.test("张三丰") && p2.test("张三丰");
            }
         * */
        System.out.println(p1.and(p2).test(name));
    }
}
  需求:姓名可以姓张,或者姓徐都满足。

 *
 * */
public class PredicateDemo03 {
    public static void main(String[] args) {
        checkName(s-> s.startsWith("张"), s -> s.startsWith("徐"),"干张徐");

    }

    public static void checkName(Predicate<String> p1 ,
                                 Predicate<String> p2,String name){
        /**
         default Predicate<T> or(Predicate<? super T> other) {
            return (t) -> test(t) || other.test(t);
                      // return p1.test("干张徐") || p2.test("干张徐");
         }
         * */
        System.out.println(p1.or(p2).test(name));
    }
}
默认方法:
      非:negate

     default Predicate<T> negate() {
         return (t) -> !test(t);
     }
      需求:如果名字是以猪开始那么就返回false。
 *
 * */
public class PredicateDemo04 {
    public static void main(String[] args) {
        checkName(s -> s.startsWith("猪") , "猪八戒");
    }

    public static void checkName(Predicate<String> p1 ,
                                 String name){
        /**
         *    default Predicate<T> negate() {
                 return (t) -> !test(t);
                  //        !p1.test("猪八戒")
              }
         *
         * */
        System.out.println(p1.negate().test(name));
        // System.out.println(!p1.test("猪八戒"));
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40932406/article/details/87862617
今日推荐