1、前言

Java 8于14年发布到现在已经有5年时间了,经过时间的磨练,毫无疑问,Java 8是继Java 5(发布于2004年)之后的又一个非常最重要的版本。因为Java 8里面出现了非常多新的特征,这些特征主要包含语言、编译器、库、工具和JVM等方面,具体如下:

  1. Lambda表达式    传送门
  2. 方法引用/构造器引用
  3. Stream API    传送门
  4. 新的日期处理类    传送门
  5. 函数式接口
  6. 接口中允许定义默认方法
  7. Optional类
  8. 重复注解、类型注解、通用类型推断
  9. 新的编译工具:jjs、jdeps
  10. JVM中的PermGen被Metaspace取代
  11. 新的Nashron引擎,允许在JVM上允许JS代码
  12. ……

以上最值得我们学习的应该就是Lambda表达式、Stream API和新的日期处理类。并不是说其他的就不用去学了,还是要去了解一下的,而这三个对我们来说很重要所以必须学习。

2、Lambda表达式简介

Lambda表达式本质上是一个匿名函数(方法),它没有方法名,没有权限修饰符,没有返回值声明。看起来就是一个箭头(->)从左边指向右边。我们可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样进行传递),它的核心思想是将面向对象中的传递数据变成传递行为。Lambda表达式的出现就是为了简化匿名内部类,让匿名内部类在方法中作为参数的使用更加方便(这里个人理解,可能有误!)。所以使用Lambda表达式可以让我们的代码更少,看上去更简洁,代码更加灵活。而Lambda表达式作为一种更紧凑的代码风格,使得Java的语言表达能力得到了提升。但也有它的缺点所在,如果Lambda表达式用的不好的话,调试运行和后期维护非常的麻烦。

3、Lambda表达式语法

Lambda表达式在Java语言中引入了一个新的语法元素和操作符。这个操作符为"->",该操作符被称为Lambda操作符或箭头操作符,它将Lambda分为两个部分:

  • 左侧:指定了Lambda表达式所需要的所有参数。
  • 右侧:指定了Lambda体,即Lambda表达式所要执行的功能。

Java8中的Lambda表达式的基本语法为:

(params) -> expression
(params) -> statement
(params) -> { statements }

上面只是基本的语法而已,所以看起来比较的简单,其中的具体使用方法有很多,如下:

①、无参数,无返回值 void。
() -> System.out.print(“Lambda…”) ;

②、有一个参数,但无返回值 void

(String s) -> System.out.print(“Lambda…”) ;

③、有参数,但是参数数据类型省略,由编译器推断,称为‘类型推断’。

(s) –> System.out.print(“Lambda…”) ;

④、若只有一个参数,方法的括号可以省略,如果多个参数则必须写上

s–> System.out.print(“Lambda…”) ;

⑤、有参数,且有返回值,如果显式返回语句时就必须使用花括号“{}”。

(s,t) –> s+t ;

(s,t) –> {return s+t;};

⑥、如果有两个或两个以上的参数,并且有多条语句则需要加上“{}”,一条执行语句可以省略。

(s,t) –> {

System.out.print(s) ;

System.out.print(t) ;

return s+t;

};

所以到目前为止,我们对Lambda表达式有了基本的认识,而前面讲了那么多的理论,就是为了接下来的快乐时光(写代码),用几个简单的例子来让我们好好理解一下Lambda表达式的使用:

public class LambdaTest {public static void main(String[] args) {//1、创建线程举例//普通写法Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Ordinary Writing");}});thread.start();//Lambda写法。无参无返回voidThread thread1 = new Thread(() -> System.out.println("Lambda Writing"));thread1.start();//2、排序举例//普通写法,默认升序List<Integer> list = Arrays.asList(26, 65, 13, 79, 6, 123);Collections.sort(list,new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1, o2);}});System.out.println(list.toString());//Lambda表达式写法。有参有返回,“类型推断”Collections.sort(list,(o1,o2)-> Integer.compare(o1,o2));System.out.println(list.toString());//3、遍历list集合//普通写法list.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});//Lambda表达式写法。遍历List集合,forEach方法中的参数是Consumer<? super T> action//其中Consumer是Java8新的新出现的函数式接口,下面会讲到函数式接口list.forEach(alist-> System.out.println(alist));//只有一个参数可省略括号}
}

注意:要使用Lambda表达式的前提是函数式接口,所以接下来学习一下函数式接口。

3、函数式接口

函数式接口(Functional Interface)也是Java8中的新特征。

函数式接口就是只能有一个抽象方法,同时可以有多个非抽象方法的接口(Java8中接口可以定义普通方法)。这样接口就可以被隐式转换为Lambda表达式。

如果我们需要自定义一个函数式接口,就需要用到Java 8提供的一个特殊的注解@FunctionalInterface,该注解会检查它是否是一个函数式接口,简单的举个函数式接口的定义例子,如下:

//定义函数式接口注解
@FunctionalInterface
public interface MyInterface {//抽象方法void method();//void method1();不能再定义//默认方法,必须用default修饰default void defaultMethod(){System.out.println("默认方法...");}//静态方法方法static void staticMethod(){System.out.println("静态方法...");}
}

上面的例子可以很容易的转换成如下Lambda表达式:

MyInterface myInterface = () -> System.out.println("MyInterface...");

我需要注意的一点是,接口中的默认方法和静态方法并不会破坏函数式接口的定义,既不会影响到Lambda表达式。同时也正因为Lambda表达式的引入,所以函数式接口也变得流行起来。

其实早在Java8之前就有很多接口是函数式接口,只是在Java8才正式提出之一特性,例如:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.util.Comparator
  • java.io.FileFilter
  • java.awt.event.ActionListener
  • ……

除了以上这些,在Java 8中还增加了一个新的包:java.util.function。它们里面包含了常用的函数式接口,该包下定义的函数式接口非常多,这里只列举比较重要的四个,如下:

(博客园的表格编辑器真的无力吐槽,实在太垃圾了,然后从其他编辑器编辑好了在截图过来!后面尝试Markdown语法吧!)

以下是这四个函数式接口的简单举例,理解Lambda表达式之后很容易写出来:

public class FunctionInterfaceTest {public static void main(String[] args) {//Consumer<T> : void accept(T t);Consumer<Integer> consumer = (a) -> System.out.println("消费型接口..."+a);consumer.accept(1000);//Function<T, R> : R apply(T t);Function<String,String> function = (b) -> b;Object apply = function.apply("函数型接口...");System.out.println(apply);//Predicate<T> : boolean test(T t);Predicate predicate = (c) -> c.equals(10);boolean test = predicate.test(10);System.out.println("断定型接口..."+test);//Supplier<T> : T get();Supplier supplier=()->(int)(Math.random() * 50);Object o = supplier.get();System.out.println("供给型接口..."+o);}
}

除了上面的这些基本的函数式接口,java.util.function包下还提供了一些针对多个参数的函数式接口,例如BiFunction<T,U,R>,它接收类型为T和U的对象,然后返回R对象。后面还有BiConsumer<T,U>、BiPredicate<T,U>等。同样还提供一些针对基本数据类型的特化函数式接口,例如XXXFunction:表示只接收XXX数据类型、XXXToXXXFunction:接收前一个XXX类型,然后返回后一个XXX类型、ToXXXFunction:表示返回值为XXX类型等等很多这样的类。(其中XXX只能是Int、Double和Long这三个基本数据类型)

如果有需要学习这些API的,可以自行去java.util.function包下查看学习,这里不多做描述。

4、方法引用和构造器引用

通过上面Lambda表达式的学习,如果你认为Lambda表达式已经让代码够简洁了,那么这里还有一个更加简洁的方法——方法引用。

简单来说,方法引用就是进一步的简化Lambda表达式声明的一种语法糖。也正是因为方法引用实在太简洁了,所以学习方法引用前必须要对Lambda表达式非常的熟悉,否则学习方法引用会有点吃力

方法引用使用操作符 “::” 将对象或类的名字和方法名分隔开来。方法引用有很多种,它们的语法如下(注意是不要写括号的):

  • 静态方法引用:ClassName::staticMethodName
  • 实例上的实例方法引用:instanceName::methodName
  • 类上的实例方法引用:ClassName::methodName
  • 父类上的实例方法引用:super::methodName
  • 构造方法引用:ClassName::new
  • 数组构造方法引用:TypeName[]::new

然后通过例子来学习方法引用如何使用吧。

这里提前说一点非常重要的:在使用方法引用时,函数式接口中的方法参数类型和个数必须和所调用的方法参数和个数一样才能使用。

    //System.out.println()简单举例@Testpublic void test() {Consumer<String> consumer = (str) -> System.out.println(str);consumer.accept("Lambda表达式");PrintStream out = System.out;Consumer consumer1 = out::println;consumer1.accept("方法引用");}

上面例子中的Consumer中的accept(T t)方法中是一个参数,而PrintStream中的println(Object x)也是一个参数,这样Lambda表达式才能转换为方法引用。

①、静态方法引用。语法格式:ClassName::staticMethodName。

    //1、静态方法用——ClassName::staticMethodName@Testpublic void test1() {//Lambda表达式BiFunction<Double, Double, Double> biFunction = (x, y) -> Math.max(x, y);System.out.println(biFunction.apply(11.1, 22.2));System.out.println("-------------");//方法引用BiFunction<Double, Double, Double> biFunction1 = Math::max;System.out.println(biFunction1.apply(33.3, 44.4));//另外一组例子,其中c1与c2是一样的Comparator<Integer> c1 = (x, y) -> Integer.compare(x, y);Comparator<Integer> c2 = Integer::compare;}

②、实例上的实例方法引用。语法格式:instanceName::methodName。

    //2、实例上的实例方法引用——instanceName::methodName@Testpublic void test2(){Consumer<String> consumer = (str) -> System.out.println(str);Consumer consumer1 = System.out::println;Person person = new Person("唐浩荣", 20, "China");Supplier supplier = () -> person.getName();Supplier supplier1  = person::getName;}

③、类上的实例方法引用。语法格式:ClassName::methodName 。

    //3、类上的实例方法引用——ClassName::methodNamepublic void test3(){BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);BiPredicate<String, String> biPredicate1 = String::equals;Function<Person, String> fun = (p) -> p.getName();Function<Person, String> fun2 = Person::getName;}

④、父类上的实例方法引用。语法格式:super::methodName。

    //4、父类上的实例方法引用——super::methodName@Testpublic void test4(){Person person=new Person();Supplier supplier = () -> super.toString();Supplier supplier1 =super::toString;}

⑤、构造方法引用。语法格式:ClassName::new。

    //5、构造方法引用——ClassName::new@Testpublic void test5() {Function<String, String> function = (n) -> new String(n);String apply = function.apply("Lambda构造方法");System.out.println(apply);Function<String, String> function1 = String::new;String apply1 = function.apply("构造方法引用");System.out.println(apply1);}

⑥、数组构造方法引用。语法格式:TypeName[]::new。

    //6、数组构造方法引用——TypeName[]::new@Testpublic void test6() {Function<Integer, Integer[]> function = (n) -> new Integer[n];//Integer integer[]=new Integer[20];Integer[] apply = function.apply(3);apply[0] = 1;for (Integer integer : apply) {System.out.println(integer);}System.out.println("-----------------");Function<Integer, Integer[]> function1 = Integer[]::new;Integer[] apply1 = function1.apply(5);apply1[0] = 11;apply1[1] = 22;for (Integer integer : apply1) {System.out.println(integer);}}

转载于:https://www.cnblogs.com/tang-hao-/p/11563226.html

夯实Java基础(二十二)——Java8新特性之Lambda表达式相关推荐

  1. Java8 新特性:Lambda 表达式、方法和构造器引用、Stream API、新时间与日期API、注解

    Java8新特性:Lambda 表达式.方法和构造器引用.Stream API.新时间与日期API.注解 1.Java8新特性 1.1.主要的新特性: 1.2.编程风格 2.Lambda 表达式 2. ...

  2. 【java8新特性】——lambda表达式与函数式接口详解(一)

    一.简介 java8于2014年发布,相比于java7,java8新增了非常多的特性,如lambda表达式.函数式接口.方法引用.默认方法.新工具(编译工具).Stream API.Date Time ...

  3. java8新特性之lambda表达式--超级详细版本

    java8新特性之lambda表达式 1.什么是lambda表达式?为什么用它? 2. 为什么Java需要lambda表达式? 3. lambda表达式的语法 4.函数式接口 4.1 什么是函数式接口 ...

  4. java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合

    java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...

  5. java:java8新特性(Lambda 表达式、方法引用、构造器引用、数组引用、Stream API)

    速度更快 对 HashMap .ConcurrentHashMap低层的数据结构(数组+链表+二叉树) 低层的内存结构(将永久区更新为元空间,元空间使用的是物理内存) 代码更少(增加了新的语法 Lam ...

  6. java8新特性总结——lambda表达式

    最近看尚硅谷java8新特性视屏,总结一下学习知识. Lambda表达式:是一个匿名函数,我们可以把Lambda理解为一段可以传递的代码(将代码像数据一样传递),可以写出更简洁更灵活的代码.作为一种更 ...

  7. lambda 对象去重_最火的java8新特性:Lambda 表达式

    主要内容 1. Lambda 表达式 2. 函数式接口 3. 方法引用与构造器引用 4. Stream API 5. 其他新特性 Java 8新特性简介 速度更快 代码更少(增加了新的语法 Lambd ...

  8. java8新特性之lambda表达式(及方法引用与构造器引用)

    Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中).使用 Lambda 表达式可以使代码变的更加简洁紧凑. 一.语法 lambda 表达式的语法格式如下: (parameters) ...

  9. java8新特性之Lambda表达式入门

    一 什么是Lambda表达式 Lambda表达式:可以让你的代码更加的简洁.ambda无法单独出现,需要一个函数式接口来盛放,可以说lambda表达式方法体是函数式接口的实现,lambda实例化函数式 ...

最新文章

  1. ubuntu 挂载 exfat 格式 U盘 mount:unknown filesystem type ‘exfat‘
  2. mysql常用转换函数_MySQL中常用转换函数介绍
  3. R语言-文本挖掘 主题模型 文本分类
  4. ASP.NET 2.0主题和皮肤实现网站美化
  5. 【POJ】3268 Silver Cow Party
  6. 未转变者服务器未正常运行,未转变者Battleye服务不能正常运行 | 手游网游页游攻略大全...
  7. paddle 标注_质量检查丨生成序号标注,究竟可以有多快多准确?
  8. python摄像头识别快递单号查询_python如何免费对接快递鸟api单号识别查询接口
  9. Java中线程的生命周期-图解
  10. android 右边抽屉,android – 抽屉在右侧抽屉中切换
  11. python自动化办公入门书籍-用Python自动办公,做职场高手(完结)
  12. socket的tcp连接中的监听套接字和已连接套接字
  13. 计算机二级c语言题库选择题,计算机二级C语言真题选择题
  14. android简单计算器源码
  15. 蒋涛对话王成录:开发者的黄金十年
  16. Kafka安全认证 SASL/PLAINTEXT,账号密码认证
  17. 发票查验一直网络异常、无法显示验证码、点击查验没反应怎么办?
  18. python图像计数_检测并计数图像中的对象
  19. pandas的DataFrame数据画图matplotlab曲线如何改变时间刻度【间隔时间】并格式化日期显示总结
  20. limbo运行veket linux,Veket Linux使用(非常适合老电脑的系统)

热门文章

  1. 【Vue2.0】—过滤器(七)
  2. 【Node】—系统模块
  3. 【Node】—nodemon的简单使用
  4. HTML之表格的基本知识
  5. c语言中 函数值类型的定义可以,C语言中,函数值类型的定义可以缺省,此时函数值的隐含类型是...
  6. mysql 时间段内的周末_淘宝用户行为数据分析(MySQL)
  7. 都是打工的,为啥职场中存在着那么多勾引斗角?
  8. 刚有个做电商的朋友在说,他们想在网上造出品牌销量很容易
  9. 原来人生真的是一场苦的修行
  10. 公司想建个FTP文件服务器,自己折腾把一台电脑做成文件服务器了,但是考虑稳定性放弃,计划买个有哪些建议?