当前位置: 移动技术网 > IT编程>开发语言>Java > Java8新特性 (一)Lambda

Java8新特性 (一)Lambda

2019年11月15日  | 移动技术网IT编程  | 我要评论
Lambda表达式 :也可称为闭包,Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中),免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力 ...

前言:

这两天彻底的复习了一遍java8的各种新特性,趁着热乎劲,把知识点整理成博客的形式保存一下。



一、lambda介绍

lambda表达式 : 也可称为闭包,lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中),免去了使用匿名方法的麻烦,并且给予java简单但是强大的函数化的编程能力


语法格式:

(parameters) -> expression
或者
(parameters) ->{ statements; }

格式说明:
():接口中抽象方法的参数列表,没有参数就空着,有参数则写出参数,多个参数用逗号分隔
->:传递的意思,将参数传递给方法体{}
{}:重写接口的抽象方法的方法体

二、lambda用法实例

1.简单实例(基础用法的规则)

1.1 无参数时,可以省略括号内容
()->10      //返回结果值:10
1.2 传入string类型的参数
(string s)->system.out.print(s)     //打印s的内容
1.3 传入的参数类型可以省略,如下
//
a->a*10         //返回结果值:a*10(传入一个参数时,可以省略括号)

(a,b)->a*b      //返回结果值:a*b(传入两个或以上参数时,不能省略括号,)


2.函数式接口

2.1 lambda实现自定义接口calculator

首先定义一个函数式接口 calculator,包含唯一一个抽象方法 calcu()

public interface calculator {
    public abstract int calcu(int x, int y);
}



其次定义一个 invokecalcu(),接收参数类型为接口

public static void invokecalcu(int x, int y, calculator calculator) {
    int sum = calculator.calcu(x, y);
    system.out.println("sum = " + sum);
}



最后调用 invokecalcu(),一共有三种方法实现:
1)使用匿名内部类传入接口,并实现抽象方法

invokecalcu(10, 20, new calculator() {
    @override
    public int calcu(int x, int y) {
        return x + y;
    }
});

2)使用lambda表达式,简化操作

invokecalcu(120, 130, (a, b) -> a + b);



2.2 lambda表达式实现多线程接口实例 runnable
//使用匿名内部类的方式实现多线程的创建
new thread(new runnable() {
    @override
    public void run() {
        system.out.println("currentthreadname = " + thread.currentthread().getname());
    }
}).start();

//使用lambda表达式实现多线程
new thread(() -> system.out.println("currentthread().getname() = " + thread.currentthread().getname())).start();



2.3 lambda表达式实现比较器接口实例 comparator

定义一个person类,保存姓名和年龄

public class person {
    private string name;
    private int age;

    public person() { }

    public person(string name, int age) {
        this.name = name;
        this.age = age;
    }

    @override
    public string tostring() {
        return "person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public string getname() { return name; }

    public void setname(string name) { this.name = name; }

    public int getage() { return age; }

    public void setage(int age) { this.age = age; }
}



然后分别使用匿名内部类和lambda表达式对person类的年龄进行排序

person[] arr = {
    new person("佟丽娅", 26),
    new person("范冰冰", 22),
    new person("柳岩", 21)
};

//匿名内部类重写comparator接口里的compare()
system.out.println("=======匿名内部类升序排序:=================");
arrays.sort(arr, new comparator<person>() {

    @override
    public int compare(person o1, person o2) {
        return o1.getage() - o2.getage();
    }
});
for (person person : arr) {
    system.out.println(person);
}

//使用lambda表达式,简化匿名内部类
system.out.println("=======lambda表达式降序排序:===============");
arrays.sort(arr, (o1, o2) -> o2.getage() - o1.getage());
/**
* jdk1.8 也可以这样写  方法引用
* arrays.sort(arr,comparator.comparingint(person::getage).reversed());
**/     
for (person person : arr) {
    system.out.println(person);
}

//stream api 也是java8的新特新写法
system.out.println("=======stream-sort升序排序:===============");
arrays.stream(arr).sorted(comparator.comparing(person::getage)).foreach(system.out::println);



接口中 有且仅有唯一一个抽象方法 ,称之为函数式接口(这种类型的接口也称为sam接口,即single abstract method interfaces)

使用前提:

  • 使用lambda必须具有接口,且要求接口中有且仅有一个抽象方法
    • 无论是 jdk内置的 runnablecomparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用lambda
  • 使用lambda必须具有上下文推断
    • 方法的参数或局部变量类型必须为lambda对应的接口类型,才能使用lambda作为该接口的实例

      有且仅有一个抽象方法的接口,称为 “函数式编程”

三、lambda变量作用域

3.1在 lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量
string[] str = {"1","12","123"};  
comparator<string> comparator = (str, second) -> integer.compare(str.length(), second.length());  //str处的编译会出错 



3.2 lambda 表达式只能引用标记了 final 的外层局部变量

也就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

可以直接在 lambda 表达式中访问外层的局部变量:

public static void main(string args[]) {
        final int num = 1;
        converter<integer, string> s = (param) -> system.out.println(string.valueof(param + num));
        s.convert(2);  // 输出结果为 3
    }
 
    public interface converter<t1, t2> {
        void convert(int i);
    }



lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

int num = 1;  
converter<integer, string> s = (param) -> system.out.println(string.valueof(param + num));
s.convert(2);
num = 5;  //由于在lambda表达式中引用了num,所以num是隐形的final修饰,但是这里修改了num的值,final就不存在了

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网