精华内容
下载资源
问答
  • java lambda表达式详解

    2021-05-08 16:57:57
    java lambda表达式详解 一、为什么要引入lambda表达式? java是一门纯面向对象的语言,如果我们需要传递某个可以复用的代码块,我们必须将代码块逻辑抽离到对象中。比如在调用Arrays.sort实现数组排序时,如果有...

    java lambda表达式详解

    一、为什么要引入lambda表达式?

    java是一门纯面向对象的语言,如果我们需要传递某个可以复用的代码块,我们必须将代码块逻辑抽离到对象中。比如在调用Arrays.sort实现数组排序时,如果有compare代码块逻辑,我们必须将其抽离到Comparator接口中,并传入Arrays.sort:

    class MyComparator implements Comparator<Integer>{
       public int compare(Integer i1, Integer i2){
           return i1 - i2 ; 
       }
    }
    ....
    Arrays.sort(array , new MyComparator) ; 
    

    在数组完成排序之前,compare方法会不断被sort方法调用。这个可复用代码块的核心逻辑其实只有一行return i1-i2; ,但是我们却写了一个类、new了一个实例来将其传递到调用到位置。这是极不方便的。而在java8引入lambda后,java也有了直接处理代码块的能力,在一定程度上支持了函数式编程。
    现在上述数组排序可以这样实现:Arrays.sort(array , (int i1 , int i2) -> i1-i2))。可以看到,通过lambda,我们能直接将代码块传入调用的位置。

    二、lambda表达式的语法

    lambda表达式结构 : (参数) -> {代码块}

    1. 即使没有参数也需要提供括号,像无参方法一样:
      () -> {System.out.println("test")}
    2. 代码块如果只有一条语句,可以忽略花括号{} ,1 中lambda表达式可以按照如下书写:
      () -> System.out.println("test")
    3. 如果通过上下文能过推导了lamda表达式的参数类型时,书写时可以忽略参数类型 :
      Comparator<Integer> comp = (i1 , i2) -> i1-i2 ;
      通过泛型Integer可以推导出参数类型为Integer,所以lambda表达式忽略了i1、i2的类型参数。(在这里能将代码块直接赋值给接口变量,是因为Comparator接口是一个函数接口,之后会提到)
    4. 无需指定lambda的返回值类型。如 3中所示,i1-i2的返回值类型要么参数类型可以推导出来
    5. 如果lambda表达式中含有分支,某些分支有返回值,某些没有是不合法的:
      (int x) - { if(x > 0) return 1 ;}

    三、函数式接口

    通俗地说:只有一个抽象方法的接口成为函数式接口。
    当我们需要一个函数式接口的对象时(如第二节中的第3点)我们可以直接提供一个lambda表达式,而不用实现接口、new对象。
    在第一节的Arrays.sort(array , (int i1 , int i2) -> i1-i2 )中,Aarrays.sort底层其实是接受了一个实现了Comparator<Integer>的接口,在sort调用接口的compare方法时,执行的是传入的lambda体。 从某种意义上说,是编译器将我们的lambda表达式自动封装进了函数式接口中,并并初始化了一个实例,显示出来就是“lambda表达式能转换成函数式接口的实例”:
    Comparator<Integer> comp = (int i1 , int i2) -> i1-i2 ;

    四、方法引用

    如果现存的方法已经能够完成某个动作时,我们可以在需要函数式接口实例的位置,直接引用该方法,而不需要再写lambda表达式。
    比如 Integer类中有静态方法:
    Integer.compare(i1 , i2)
    该方法是用来比较两个整数的方法,源码如下:

    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }
    

    该方法可以实现比较两个整数,并返回int类型的值,符合比较器的逻辑。那么我们在实现Arrays.sort时可以这样写:
    Arrays.sort(array , Integer::compare)即引用Integer的compare方法。
    三种方法对比:

    '''第一种,实现接口'''
    class MyComparator implements Comparator<Integer>{
        public int compare(Integer i1, Integer i2){
            return i1 - i2 ; 
        }
    }
    ....
    Arrays.sort(array , new MyComparator()) ; 
    
    '''第二种,使用lambda表达式'''
    Arrays.sort(array 
                , (int i1 , int i2) -> (x < y) ? -1 : ((x == y) ? 0 : 1) ) ; 
                
    '''第三种,使用方法调用'''
    Arrays.sort(array,Integer::compare);
    

    必须注意的是在第三种方式中,没有像lambda表达式一样显式的声明方法的参数和返回值 ,这是因为编译器能够从引用中获得该方法的参数和返回值,并与原本的函数式接口中的方法作对比。
    因此:引用的方法的参数数量和类型、返回值都必须和原来函数式接口中的方法一样。比如Integer.compare和Comparator.compare方法在参数的数量类型、返回值类型上一致,如下:

    // Integer.compare的定义
    public static int compare(int x, int y) 
    // Compatator.compare的定义
    int compare(T o1, T o2);
    

    所以方法引用Integer::compare 能够转换成Comparetor接口的实例。
    方法引用有三种形式:

    1. Class::staticMethod 引用某类型的静态函数 ,如:Math::pow , 等同于:(x, y) -> Math.pow(x,y)
    2. Object::instanceMethod 引用某实例的实例方法 ,效果与第一种相同,且this::instanceMethod和super::instanceMethod是合法的。
    3. Class::instanceMethod 引用某类型的实例方法,实例是传入的第一个参数,
      如String::equels 等同于 :(String x , String y)-> x.equles(y)
      五、构造器引用
      构造器是一种特殊的方法,可以直观地理解为方法引用。引用形式为Class::new。由于使用的较少,在这里不赘述,有兴趣的同学可以自行了解。

    六、lambda表达式访问外部变量

    lambda可以在代码体中访问lambda表达式外的变量,如下所示:首先定义了一个函数式接口,然后在第8行代码,使用将printMsg方法的参数写入到lambda代码体中。

    @FunctionInterface 
    interface MyfunctionIT{ 
        void print() ; 
    }
    
    public static void printMsg(String text)
    {
        repeatPrint(() -> System.out.println(text)); 
    }
    
    public void repeatPrint(MyfunctionIT printIt){
        for(int i= 0 ; i<100 ; i++){
            printIt.print();
        }    
    }
    

    值得注意的是lambda表达是引用的外部变量不可以改变,这和局部内部类的特性有关。

    七、处理lambda表达式

    lambda表达式的重点是延迟执行。在我们需要多次运行代码、回调时再运行代码等等非立即执行的时候,就可以将代码块包装成lambda表达,转化为一个函数式接口实例。比如某个动作想要重复10次:
    repeat(10 , ()-> System.out.println("Hello , World !"))要接收这个lambda表达式,我们就需要一个接口:

    reapet(int n , Runable action){
        for(int i = 0 ; i < n ; i++){
            action.run();
        }
    }
    

    在这里,我们使用了Runable接口。当acrion.run执行时,会执行我们传入的lambda表达式。
    在进行方法设计时,我们可以利用系统提供的函数式接口:
    常用函数式接口

    值得注意的是,在高性能需求的场景下。对于基本类型的参数传递,我们需要注意减少自动装箱的开销。比如将接口Consumer 替换为不需要包装类型的IntConsumer接口:

    interface Consumer<Integer>{
        void accept(Integer i);
    }
    
    @FounctionalInterface
    interface IntConsumer{
        void accept(int i);
    }
    

    如果自定义函数式接口最好使用@FounctionalInterface定义,一是做标识,二是确保接口只有一个抽象方法。

    八、再谈Comparator

    Comparator中提供了很多静态方法来创建比较器。比如:comparing方法能够提取类型T中一个键s,将该类型T转化为按照键s可比较的(Comparable)。假设有一个Person对象数组,可如下按名字对数组进行排序:

    Arrays.sort(people , 
                Comparator.comparing(Person::getFirstName)
                          .thanComparing(Persion::getSecondName));
    

    comparing函数接收的是一个方法引用,返回的也是一个比较器实例。Person::getFirstName称为键函数。
    上述例子的结果是,先用FirstName排序,如果相同,再依照SecondName排序。默认按照字典序排序。
    如果我们需要对名字按照长度排序如何自定义呢?如下所示,可以在comparing方法的第二个参数位置传入一个自定义比较器:

      Arrays.sort(people , 
              Comparator.comparing(Person::getFirstName , (s,t) -> s.length - t.length);
    

    这里传入的比较器使用的是lambda表达式。
    对于上述动作,也可以直接使用变体Arrays.sort(people , Comparator.comparInt((p) -> p.getName().getlength()))
    如果键函数可以返回null,还需要用到nullsFirst和nullsLast适配器。这里不赘述,需要了解的读者可以自行了解。

    九、lambda表达式的原理

    参考文章Lambda表达式实现原理分析

    public class LambdaTest {
        public static void printString(String s, Print<String> print) {
            print.print(s);
        }
        public static void main(String[] args) {
            printString("test", (x) -> System.out.println(x));
        }
    }
    
    @FunctionalInterface
    interface Print<T> {
        public void print(T x);
    }
    

    经过反编译分析还原:

    public class LambdaTest {
        public static void PrintString(String s, Print<String> print) {
            print.print(s);
        }
    
        public static void main(String[] args) {
            PrintString("test", new LambdaTest$$Lambda$1()); // 传入内部类实例
        }
    
        //lambda表达式代码逻辑的私有静态方法
        private static void lambda$main$0(String x) {
            System.out.println(x);
        }
    
        // 生成内部类,内部类实现了接口
        static final class LambdaTest$$Lambda$1 implements Print {
            public void print(Object obj) {
                LambdaTest.lambda$main$0((String) obj); //调用lambda私有静态方法
            }
            private LambdaTest$$Lambda$1() {
            }
        }
    
    }
    
    @FunctionalInterface
    interface Print<T> {
        public void print(T x);
    }
    

    过程:

    1. 在类编译时,会生成一个私有静态方法+一个内部类;
    2. 在内部类中实现了函数式接口,在实现接口的方法中,会调用编译器生成的静态方法;
    3. 在使用lambda表达式的地方,通过传递内部类实例,来调用函数式接口方法。

    参考资料

    《java核心技术-卷1》

    展开全文
  • Java Lambda表达式详解

    2021-03-24 14:34:09
    Java lambda表达式的理解与应用

    Lambda表达式详解

    什么情况下使用:

    我们以前写一些类,写完发现只使用一次,这时候我们会把类从外部类拉到内部类,再进一步的是提升为匿名内部类,然后Java为了更加的简高效,所以有了Lambda表达式

    作用及其本质:

    (1)作用:避免匿名内部类定义过多
    (2) 本质:属于函数式编程的概念,去掉没有意义的代码,只留下核心的逻辑

    预备知识

    Function Interface(函数式接口):任何接口,如果只包含一个抽象方法,那它就是函数式接口
    例如`:

    public interface Runnable{
    	public abstract void run();
    }
    

    演化代码:

    package com.heima.Multithreading;
    
    public class TestLambda {
        //3.静态内部类 02
        static class Like2 implements Ilike{
    
            @Override
            public void lambda() {
                System.out.println("i like lambda 02");
            }
        }
    
        public static void main(String[] args) {
            //01 创建对象,接口去new上一个实现类
            Ilike like = new Like();
            like.lambda();
    
            //02 调用静态内部类
            like = new Like2();//这里还是用了上面的like
            like.lambda();
    
            //4.局部内部类 03
            class Like3 implements Ilike{
    
                @Override
                public void lambda() {
                    System.out.println("i like lambda 03");
                }
            }
    
            //03 调用局部内部类
            like = new Like3();//这里还是用了上面的like
            like.lambda();
    
            //5.匿名内部类,没有类的名称,必须借助接口或者父类 04
            like = new Ilike() {
                @Override
                public void lambda() {
                    System.out.println("i like lambda 04");
                }
            };
            like.lambda();
    
            //6.用lambda简化
            like = ()->{
                System.out.println("i like lambda 05");
            };
            like.lambda();
    
    
    
        }
    }
    
    //1.定义一个函数式接口
     interface Ilike{
        void lambda();
    }
    
    //2.外部实现类 01
    class Like implements Ilike{
    
        @Override
        public void lambda() {
            System.out.println("i like lambda 01");
        }
    }
    

    在这里插入图片描述

    重点解释:

    在这里插入图片描述
    lambda表达式,可以理解为只要了匿名内部类的这一部分核心代码,把其他无所谓的去掉了(多加了个箭头)

    练习2:带参数

    外部类

    package com.heima.Multithreading;
    
    public class TestLambda2 {
        public static void main(String[] args) {
            Ilove love = new Love();
            love.love(250);
        }
    }
    interface Ilove{
        void love(int a);
    }
    class Love implements Ilove{
    
        @Override
        public void love(int a) {
            System.out.println("i love you--->"+a);
        }
    }
    
    

    在这里插入图片描述

    静态内部类:

    package com.heima.Multithreading;
    
    public class TestLambda2 {
    
        static class Love implements Ilove{
    
            @Override
            public void love(int a) {
                System.out.println("i love you--->"+a);
            }
        }
    
        public static void main(String[] args) {
            Ilove love = new Love();
            love.love(251);
        }
    }
    interface Ilove{
        void love(int a);
    }
    
    
    

    在这里插入图片描述

    匿名内部类

    package com.heima.Multithreading;
    
    public class TestLambda2 {
       
        public static void main(String[] args) {
            Ilove love = new Ilove() {
                @Override
                public void love(int a) {
                    System.out.println("i love you--->"+a);
                }
            };
            love.love(251);
        }
    }
    interface Ilove{
        void love(int a);
    }
    
    
    

    在这里插入图片描述

    Lambda表达式

    package com.heima.Multithreading;
    
    public class TestLambda2 {
    
    
        public static void main(String[] args) {
    
    
            //lambda表达式
            Ilove love = (int a)->{
                    System.out.println("i love you--->"+a);
                };
    
            //lambda表示是简化1:去掉参数类型,有多个参数时,要去掉都去掉
             love = (a)->{
                System.out.println("i love you--->"+a);
            };
             //Lambda表达式简化2:去掉括号,当只有一个参数时
            love = a->{
                System.out.println("i love you--->"+a);
            };
    
            //lambda表达式简化3:去掉花括号
            //当只有一行代码时
            love = a-> System.out.println("i love you--->"+a);
            
            
            love.love(253);
    
    
        }
    }
    interface Ilove{
        void love(int a);
    }
    
    
    
    

    在这里插入图片描述

    Lambda表达式简化总结:

    简化最好只简化参数类型 , 其他很少用到

    展开全文
  • Java Lambda 表达式详解

    2021-03-17 12:41:28
    Lambda 表达式是一个可传递的代码块,可以在以后执行一次或多次。 语法表达式形式:参数,箭头(->),以及一个表达式。例如: (String first, String second) -> first.length() - second.length() 如果代码要...

    Lambda 表达式是一个可传递的代码块,可以在以后执行一次或多次。

    语法

    表达式形式:参数,箭头(->),以及一个表达式。例如:


    (String first, String second) -> first.length() - second.length()

    如果代码要完成的计算无法放在一个表达式中,就可以像写方法一样,把这些代码放在{}中,并包含显示的return语句。例如:

    (String first, String second)-> {

    if(first.length() < second.length()) return -1;

    else if(first.length() > second.length()) return 1;

    else return 0;

    }

    即使lambda表达式没有参数,仍然要提供空括号,就像无参数方法一样:

    () -> {for (int i = 100; i >= 0; i—) System.out.println(i);}

    如果可以推导出一个lambda表达式的参数类型,则可以忽略其类型。例如:

    Comparator<String> comp = (first, second) -> first.length() - second.length();

    在这里,编译器可以推导出first和second必然是字符串,因为这个lambda表达式将赋给一个字符串比较器。

    如果方法只有一个参数,而且这个参数的类型可以推导得出,那么甚至还可以省略小括号:

    ActionListener listener = event -> System.out.println(“test”);

    无须指定lambda表达式的返回类型。lambda表达式的返回类型总是会由上下文推导得出。例如:

    (String first, String second) -> first.length() - second.length()

    可以在需要int类型结果的上下文中使用。

    注释:如果lambda表达式只在某些分支返回一个值,而另外一些分支不返回值,这是不合法的。例如:

    (int x) -> { if (x >= 0) return 1; }//不合法

    函数式接口

    对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式,这种接口成为函数式接口(functional interface)。例如:

    Arrays.sort(words,(first, second) -> first.length() - second.length());

    在底层,Arrays.sort 方法会接受实现了Comparator的某个类的对象。在这个对象上调用compare方法会执行这个lambda表达式的体。

    注释:最好把lambda表达式看作是一个函数,而不是一个对象,另外要接受lamda表达式可以传递到函数式接口。实际上在Java中,对lambda表达式所能做的也只是转换为函数式接口,Java设计者没有为Java语言增加函数类型(在其他程序设计语言中,可以声明函数类型的变量)。不能把lambda表达式赋值给类型为Object的变量,因为Object不是函数式接口。

    java.util.function 包中定义了很多非常通用的函数式接口。例如:

    Predicate

    public interface Predicate<T> {

    boolean test(T t);

    //additional default and static methods

    }

    ArrayList类中有一个removeIf方法,它的参数就是一个Predicate。这个接口专门用来传递lambda表达式。例如,下面的语句将从一个数组列表中删除所有的null值:

    list.removeIf(e -> e == null);

    Supplier

    public interface Supplier<T> {

    T get();

    }

    供应者(supplier)没有参数,调用时会生成一个T类型的值。供应者用于实现计算:例如:

    LocalDate hireDay = Objects.requireNonNullOrElse(day, new LocalDate(1970,1,1));

    这不是最优的,我们与day很少为null,所以希望只在必要时才构造默认的LocalDate,通过使用供应者,我们就能延迟这个计算:

    LocalDate hireDay = Objects.requireNonNullOrElseGet(day, () -> new LocalDate(1970,1,1));

    requireNonNullOrElseGet 方法只在需要值时才调用供应者。

    方法引用

    有时,lambda表达式涉及一个方法。例如:

    var timer = new Timer(1000, event -> System.out.println(event));

    但是,如果直接把println方法传递到Timer构造器就更好了。具体做法如下:

    var timer = new Timer(1000,System.out::println);

    表达式System.out::println是一个方法引用(method reference),他只是编译器生成一个函数式接口的实例,覆盖整个接口的抽象方法来调用给定的方法。在这个例子中,会生成一个 ActionListener,它的 actionPerformed(ActionEvent e) 方法要调用 System.out.println(e)。

    注释:类似于lambda表达式,方法引用也不是一个对象。不过,为一个类型为函数式接口的变量赋值时会生成一个对象。

    再来看一个例子,假设想对字符串进行排序,而不考虑字母的大小写,可以传递以下方法表达式:

    Arrays.sort(strings,String::compareToIgnoreCase)

    小结:要用::运算符分割方法与对象或者类名。主要有3种情况:

    1. object::instanceMethod
    2. Class::instanceMethod
    3. Class::staticMethod

    在第1种情况下,方法引用等价于向方法传递参数的lambda表达式。对于System.out::println,对象是 System.out,所以方法表达式等价于 x -> System.out.println(x)

    对于第2种情况,第1个参数会成为方法的隐式参数。例如,String::compareToIgnoreCase

    等同于(x, y) -> x.compareToIgnoreCase(y)

    在第3种情况下,所有参数都会传递到静态方法:Math::pow等价于(x, y) -> Math.pow(x, y)

    :只有当lambda表达式的体只调用一个方法而不做其他操作时,才能把lambda表达式重写为方法引用。考虑以下表达式:

    s -> s.length == 0

    这里有一个方法调用。但是还是有一个比较,所以这里不能使用方法引用。

    构造器引用

    构造器引用与方法引用很类似,只不过方法名为new。例如,Person::new 是 Person 构造器的一个引用。

    可以用数组类型简历构造器引用。例如,int[]::new是一个构造器引用,他有一个参数:即数组的长度。这等价于lambda表达式x -> new int[x]

    Java有一个限制,无法构造泛型类型T的数组。但是利用数组构造器可以克服这个限制,例如:

    Person[] people = stream.toArray(Person[]::new);

    toArray方法调用这个构造器来得到一个有正确类型的数组。然后填充并返回这个数组。

    变量作用域

    lambda 表达式有3个部分:

    1. 一个代码块;
    2. 参数;
    3. 自由变量的值,这里指非参数而且不在代码中定义的变量

    lambda表达式中访问外围方法或者类中的变量。lambda表达式中捕获的变量必须实际上是事实最终变量(effectively final),事实最终变量是指,这个变量初始化之后就不会再为它赋新值。在下面例子中,text总是指示同一个String对象,所以捕获这个变量是合法的。

    public static void repeatMessage(String text){
    ActionListener listener = event -> {
    System.out.println(text);
    }
    }

    在lambda表达式中,只能引用值不会改变的变量(因为,如果在lambda表达式中更改变量,并发执行多个动作是就会不安全),下面这种做法是不合法的:

    public static void countDown(int start){
    ActionListener listener = event -> {
    start--; //ERROR:Can’t mutate captured variable
    System.out.println(start);

    }
    }

    如果在lambda表达式中引用一个变量,而这个变量可能在外部改变,这也是不合法的。例如:

    public static void repeat(String text, int count){
    for(int i = 1; i <= count; i++){
    ActionListener listener = event -> {
    //i的值会改变,因此不能捕获i
    System.out.println(String.valueOf(i) + text);
    }
    }
    }

    注:

    1. lambda表达式的体与嵌套块有相同的作用域。所以这里同样适用命名冲突和遮蔽的有关规则。在lambda表达式中声明与一个局部变量同名的参数或局部变量是不合法的。
    2. 在一个lambda表达式中使用this关键字时,是指创建这个lambda表达式的方法的this参数
    public class Application{
    public void init(){
    ActionListener listener = event -> {
    System.out.println(this.toString());
    }
    }
    }

    表达式this.toString()会调用Application对象的toString方法,而不是ActionListener实例的方法。

    处理lambda表达式

    如何编写方法处理lambda表达式?,使用lambda表达式的重点是延迟执行

    1. 需要选择一个合适的函数式接口
    2. 可以选择自定义函数式接口,建议使用@FunctionalInterface注解标记这个接口,这样如果无意中增加了另一个抽象方法,编译器就会产生一个错误消息

    再谈Comparator

    Comparator接口包含很多方便的静态方法来创建比较器,这些方法可以用于lambda表达式或方法引用。

    参考资料

    Core Java Volume I — Fundamentals (Eleventh Edition)

    展开全文
  • Java lambda表达式详解

    2017-09-30 10:54:00
    Java lambda表达式是一种很有用很方便很常见的语法,先据一个例子: public class Java8Tester { public static void main(String args[]){ Java8Tester tester = new Java8Tester(); //with type ...

    Java lambda表达式是一种很有用很方便很常见的语法,先据一个例子:

    public class Java8Tester {
       public static void main(String args[]){
          Java8Tester tester = new Java8Tester();
    		
          //with type declaration
          MathOperation addition = (int a, int b) -> a + b;
    		
          //with out type declaration
          MathOperation subtraction = (a, b) -> a - b;
    		
          //with return statement along with curly braces
          MathOperation multiplication = (int a, int b) -> { return a * b; };
    		
          //without return statement and without curly braces
          MathOperation division = (int a, int b) -> a / b;
    		
          System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
          System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
          System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
          System.out.println("10 / 5 = " + tester.operate(10, 5, division));
    		
          //without parenthesis
          GreetingService greetService1 = message ->
          System.out.println("Hello " + message);
    		
          //with parenthesis
          GreetingService greetService2 = (message) ->
          System.out.println("Hello " + message);
    		
          greetService1.sayMessage("Mahesh");
          greetService2.sayMessage("Suresh");
       }
    	
       interface MathOperation {
          int operation(int a, int b);
       }
    	
       interface GreetingService {
          void sayMessage(String message);
       }
    	
       private int operate(int a, int b, MathOperation mathOperation){
          return mathOperation.operation(a, b);
       }
    }
    

      可以看出Java lambda表达式的形式为 parameter -> expression。上面程序中如果不用lambda表达式,也可以实现,比如用类实现接口,然后生成对象,再调用之类的,或者好一点,也是用一个匿名类,但是这样会非常麻烦,远远没有lambda表达式简洁.

    再看另一个例子。如果有一个Person列表,Person包含年龄,性别,名字等字段,现在要写一个根据条件过滤这个列表并打印出来等程序,用lambda表达式可以这么做:

     

    import java.util.ArrayList;
    import java.util.List;
    import java.util.function.Consumer;
    import java.util.function.Predicate;
    
    class Person {
    
        public enum Sex {
            MALE, FEMALE
        }
    
        String name;
    
        Sex gender;
    
        int age;
    
        String emailAddress;
    
        public int getAge() {
            return age;
        }
    
        public Sex getGender() {
            return gender;
        }
    
        public void setGender(Sex gender) {
            this.gender = gender;
        }
    
        public void printPerson() {
            System.out.println( "The name is: "+ name + " at age: "+ age);
        }
    
        public Person(String name, Sex gender, int age, String emailAddress) {
            this.name = name;
            this.gender = gender;
            this.age = age;
            this.emailAddress = emailAddress;
        }
    }
    
    public class Main {
        public static void printPersonsWithPredicate(List<Person> roster, Predicate<Person> tester) {
            for (Person p : roster) {
                if (tester.test(p)) {
                    p.printPerson();
                }
            }
        }
    
        public static void processPersons(
                List<Person> roster,
                Predicate<Person> tester,
                Consumer<Person> block) {
            for (Person p : roster) {
                if (tester.test(p)) {
                    block.accept(p);
                }
            }
        }
    
        public static void main(String[] args){
            List<Person> pl = new ArrayList();
            pl.add(new Person("Jet", Person.Sex.MALE, 21, "Jet@163.com"));
            pl.add(new Person("Mike", Person.Sex.MALE, 18, "Mike@163.com"));
            pl.add(new Person("Jim", Person.Sex.MALE, 28, "Jim@163.com"));
            pl.add(new Person("Lucy", Person.Sex.FEMALE, 20, "Lucy@163.com"));
            pl.add(new Person("Diana", Person.Sex.FEMALE, 28, "Diana@163.com"));
    
            printPersonsWithPredicate(
                    pl,
                    p -> p.getGender() == Person.Sex.FEMALE
                            && p.getAge() >= 18
                            && p.getAge() <= 25
            );
    
            System.out.println("==========================");
    
            processPersons(
                    pl,
                    p -> p.getGender() == Person.Sex.MALE
                            && p.getAge() >= 18
                            && p.getAge() <= 25,
                    p -> p.printPerson()
            );
        }
    }
    

     

     

    可以看到这里分别调用了Java的标准接口Predicate和Consumer,返回类型不同需要注意,然后我们用lambda表达式逻辑上实现它的test方法和accept,就可以正确使用了,是不是很方便?

     

    转载于:https://www.cnblogs.com/huangzifu/p/7614107.html

    展开全文
  • 主要介绍了Java Lambda表达式详细介绍,从简单的到复杂的实例讲解,需要的朋友可以参考下
  • 1 Lambda表达式Java8中的新特性Java8中引入Lambda表达式,使得java可以函数式编程,在并发性能上迈出了实质性的一步。 什么是函数式编程?函数式编程(英语:functional programming)或称函数程序设计,又称泛函...
  • 本文主要介绍Java Lambda 表达式的知识,这里整理了相关资料,JavaLambda 是Java8 引入的新功能,有兴趣的小伙伴可以参考下
  • 什么是lambda表达式?可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。比如说new一个Thread的传统写法如下那么...
  • 我们对 Java8 似乎抱有更大的期待,因为它是 Java5 之后最重要的一次升级,提供了十多个新特性,其中 Lambda 表达式Java8 新特性中最重要的一个。Lambda 表达式允许开发者将函数作为参数传给某个方法,即支持函数...
  • 课程目标: 通过本课程的学习,详细掌握Java8新特性之Lambda表达式;适用人群:有Java基础的开发人员; 课程概述:从Java 8出现以来lambda是最重要的特性之一,它可以让我们用简洁流畅的代码完成一个功能。很长一段...
  • 简介Lambda表达式Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码...
  • lambda表达式介绍python中有一种灵活,便捷的且具有函数功能的表达式:lambda表达式lambda表达式,又称匿名函数,是现代各种编程语言争相引入的一种语法,其功能堪比函数,设计却比函数简洁。python lambda表达式...
  • 一、为什么要使用lambda表达式如果之前见到的话都会觉得,lambda就是一个匿名函数,我们可以这样来理解就好了,Lambda表达式就是为了使得我们的代码更加的简洁。如何简洁呢?我们直接举个例子来看看:之前我...
  • 亲爱的小伙伴们,本期我们讲解java中的正则表达式和它相关的一些类与方法。概述正则表达式非常强大,能够解决我们开发时用于匹配一些特定的要求。并且java中还提供了相当强大的方法,扩展其功能性。下面我们就来介绍...
  • Java Lambda 表达式Java 8 引入的一个新的功能,可以说是模拟函数式编程的一个语法糖,类似于 Javascript 中的闭包,但又有些不同,主要目的是提供一个函数化的语法来简化我们的编码。Lambda 基本语法Lambda 的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,543
精华内容 617
热门标签
关键字:

javalambda表达式详解

java 订阅