首页编程java编程java8 lambda有什么用?Java8新特性lambda表达式有什么用

java8 lambda有什么用?Java8新特性lambda表达式有什么用

编程之家2023-10-14103次浏览

大家好,今天小编来为大家解答java8 lambda有什么用这个问题,Java8新特性lambda表达式有什么用很多人还不知道,现在让我们一起来看看吧!

java8 lambda有什么用?Java8新特性lambda表达式有什么用

java8 lambda 表达式是个什么

为了支持函数式编程,Java 8引入了Lambda表达式.

在Java 8中采用的是内部类来实现Lambda表达式.具体实现代码,可以通过debug看,同时通过字节码查看工具及反编译工具来验证.

自从lambda表达式成为Java语言的一部分之后,Java集合(Collections)API就面临着大幅变化。而JSR 355(规定了Java lambda表达式的标准)的正式启用更是使得Java集合API变的过时不堪。

java8 lambda有什么用?Java8新特性lambda表达式有什么用

尽管我们可以从头实现一个新的集合框架(比如“Collection II”),但取代现有的集合框架是一项非常艰难的工作,因为集合接口渗透了Java生态系统的每个角落,将它们一一换成新类库需要相当长的时间。因此,我们决定采取演化的策略(而非推倒重来)以改进集合API:为现有的接口(例如Collection,List和Stream)增加扩展方法;

在类库中增加新的流(stream,即java.util.stream.Stream)抽象以便进行聚集(aggregation)操作;

改造现有的类型使之可以提供流视图(stream view);

java8 lambda有什么用?Java8新特性lambda表达式有什么用

改造现有的类型使之可以容易的使用新的编程模式,这样用户就不必抛弃使用以久的类库,例如ArrayList和HashMap

(当然这并不是说集合API会常驻永存,毕竟集合API在设计之初并没有考虑到lambda表达式。我们可能会在未来的JDK中添加一个更现代的集合类库)。

除了上面的改进,还有一项重要工作就是提供更加易用的并行(Parallelism)库。尽管Java平台已经对并行和并发提供了强有力的支持,然而开发者在实际工作(将串行代码并行化)中仍然会碰到很多问题。因此,我们希望Java类库能够既便于编写串行代码也便于编写并行代码,因此我们把编程的重点从具体执行细节(how computation should be formed)转移到抽象执行步骤(what computation should be perfomed)。

Java8新特性lambda表达式有什么用

Java 8终于引进了lambda表达式,这标志着Java往函数式编程又迈进了一小步。

在Java 8以前的代码中,为了实现带一个方法的接口,往往需要定义一个匿名类并复写接口方法,代码显得很臃肿。比如常见的Comparator接口:

String[]oldWay="ImprovingcodewithLambdaexpressionsinJava8".split("");

Arrays.sort(oldWay,newComparator<String>(){

@Override

publicintcompare(Strings1,Strings2){

//忽略大小写排序:

returns1.toLowerCase().compareTo(s2.toLowerCase());

}

});

System.out.println(String.join(",",oldWay));

对于只有一个方法的接口,在Java 8中,现在可以把它视为一个函数,用lambda表示式简化如下:

String[]newWay="ImprovingcodewithLambdaexpressionsinJava8".split("");

Arrays.sort(newWay,(s1,s2)->{

returns1.toLowerCase().compareTo(s2.toLowerCase());

});

System.out.println(String.join(",",newWay));

Java 8没有引入新的关键字lambda,而是用()->{}这个奇怪的符号表示lambda函数。函数类型不需要申明,可以由接口的方法签名自动推导出来,对于上面的lambda函数:

(s1,s2)->{

returns1.toLowerCase().compareTo(s2.toLowerCase());

});

参数由Comparator<String>自动推导出String类型,返回值也必须符合接口的方法签名。

实际上,lambda表达式最终也被编译为一个实现类,不过语法上做了简化。

对于Java自带的标准库里的大量单一方法接口,很多都已经标记为@FunctionalInterface,表明该接口可以作为函数使用。

以Runnable接口为例,很多时候干活的代码还没有定义class的代码多,现在可以用lambda实现:

publicstaticvoidmain(String[]args){

//oldway:

RunnableoldRunnable=newRunnable(){

@Override

publicvoidrun(){

System.out.println(Thread.currentThread().getName()+":OldRunnable");

}

};

RunnablenewRunnable=()->{

System.out.println(Thread.currentThread().getName()+":NewLambdaRunnable");

};

newThread(oldRunnable).start();

newThread(newRunnable).start();

}

在未来的Java代码中,会出现越来越多的()->{}表达式。

为什么要使用lambda表达式原来如此,涨知识了

先看几段Java8以前经常会遇到的代码:

创建线程并启动

比较数组

给按钮添加单击事件

对于这三段代码,我们已经司空见惯了。

Java复杂冗余的代码实现一直被程序员所诟病,好在随着JVM平台语言Scala的兴起以及函数式编程风格的风靡,让Oracle在Java的第8个系列版本中进行了革命性的变化,推出了一系列函数式编程风格的语法特性,比如Lambda表达式以及Stream。

如果采用Lambda表达式,上面三段代码的实现将会变得极为简洁。

创建线程并启动(采用Lambda版本)

比较数组(采用Lambda版本)

给按钮添加单击事件(采用Lambda版本)

格式:(参数)->表达式

其中:

一个参数

多个参数

0个参数

表达式块

在Java8中新增加了一个注解: [@FunctionalInterface],函数式接口。

什么是函数式接口呢?它包含了以下特征:

Lambda表达式的本质就是函数式接口的匿名实现。只是把原有的接口实现方式用一种更像函数式编程的语法表示出来。

Java8的java.util.function包已经内置了大量的函数式接口,如下所示:

从中可以看出:

以下是一个综合的例子:

如果觉得这些内置函数式接口还不够用的话,还可以自定义自己的函数式接口,以满足更多的需求。

如果Lambda表达式已经有实现的方法了,则可以用方法引用进行简化。方法引用的语法如下:

这样前面提到的Lambda表达式:

则可以替换为:

另一个例子:

可以替换为:

注意:方法名后面是不能带参数的!可以写成System.out::println,但不能写成System.out::println(“hello”)

如果能获取到本实例的this参数,则可以直接用this::实例方法进行访问,对于父类指定方法,用super::实例方法进行访问。

下面是一个例子:

构造器引用和方法引用类似,只不过函数接口返回实例对象或者数组。构造器引用的语法如下:

举个例子:

其中的labels.stream().map(Button::new)相当于 labels.stream().map(label->new Button(label))

再看个数组类型的构造器引用的例子:

把Stream直接转成了数组类型,这里用Button[]::new来标示数组类型。

先看一段代码:

一个lambda表达式一般由以下三部分组成:

参数和表达式好理解。那自由变量是什么呢?它就是在lambda表达式中引用的外部变量,比如上例中的text和count变量。

如果熟悉函数式编程的同学会发现,Lambda表达式其实就是”闭包”(closure)。只是Java8并未叫这个名字。对于自由变量,如果Lambda表达式需要引用,是不允许发生修改的。

比如下面的代码:

先说说为什么要在Java8接口中新增默认方法吧。

比如Collection接口的设计人员针对集合的遍历新增加了一个forEach()方法,用它可以更简洁的遍历集合。比如:

但如果在接口中新增方法,按照传统的方法,Collection接口的自定义实现类都要实现forEach()方法,这对广大已有实现来说是无法接受的。

于是Java8的设计人员就想出了这个办法:在接口中新增加一个方法类型,叫默认方法,可以提供默认的方法实现,这样实现类如果不实现方法的话,可以默认使用默认方法中的实现。

一个使用例子:

默认方法的加入,可以替代之前经典的接口和抽象类的设计方式,统一把抽象方法和默认实现都放在一个接口中定义。这估计也是从Scala的Trait偷师来的技能吧。

除了默认方法,Java8还支持在接口中定义静态方法以及实现。

比如Java8之前,对于Path接口,一般都会定义一个Paths的工具类,通过静态方法实现接口的辅助方法。

接口中有了静态方法就好办了,统一在一个接口中搞定!虽然这看上去破坏了接口原有的设计思想。

这样Paths类就没什么意义了~

使用Lambda表达式后可以大幅减少冗余的模板式代码,使把更多注意力放在业务逻辑上,而不是复制一堆重复代码,除非你在一个用代码行数来衡量工作量的公司,你觉得呢?

OK,本文到此结束,希望对大家有所帮助。

java 中的函数是什么 Java的函数具体是什么意思,是怎么作用的应该怎么写java程序员可以做什么 Java程序员可以从事哪些工作