快8彩票平台

欢迎光临北大青鸟佛山华大校区,了解更多关于课程学费等请咨询在线老师!

我的位置: 快8彩票平台 >>Java Lambda 表达式学习笔记

Java Lambda 表达式学习笔记

2019-05-14

来源:北大青鸟佛山华大校区

 
  JavaLambda表达式是Java8引入的一个新的功能,可以说是模拟函数式编程的一个语法糖,类似于Javascript中的闭包,但又有些不同,主要目的是提供一个函数化的语法来简化我们的编码。

  Lambda基本语法

  Lambda的基本结构为(arguments)->body,有如下几种情况:

  参数类型可推导时,不需要指定类型,如(a)->System.out.println(a)

  当只有一个参数且类型可推导时,不强制写(),如a->System.out.println(a)

  参数指定类型时,有括号,如(inta)->System.out.println(a)

  参数可以为空,如()->System.out.println(“hello”)

  body需要用{}包含语句,当只有一条语句时{}可省略

  常见的写法如下:

  (a)->a*a

  (inta,intb)->a+b

  (a,b)->{returna-b;}

  ()->System.out.println(Thread.currentThread().getId())

  函数式接口FunctionalInterface

  概念

  JavaLambda表达式以函数式接口为基础。什么是函数式接口(FunctionalInterface)?简单说来就是只有一个方法(函数)的接口,这类接口的目的是为了一个单一的操作,也就相当于一个单一的函数了。常见的接口如:Runnable,Comparator都是函数式接口,并且都标注了注解@FunctionalInterface。

  举例

  以Thread为例说明很容易理解。Runnable接口是我们线程编程时常用的一个接口,就包含一个方法voidrun(),这个方法就是线程的运行逻辑。按照以前的语法,我们新建线程一般要用到Runnable的匿名类,如下:

  newThread(newRunnable(){

  @Override

  publicvoidrun(){

  System.out.println(Thread.currentThread().getId());

  }

  }).start();

  如果写多了,是不是很无聊,而基于Lambda的写法则变得简洁明了,如下:

  newThread(()->System.out.println(Thread.currentThread().getId())).start();

  注意Thread的参数,Runnable的匿名实现就通过一句就实现了出来,写成下面的更好理解

  Runnabler=()->System.out.println(Thread.currentThread().getId());

  newThread(r).start();

  当然Lambda的目的不仅仅是写起来简洁,更高层次的目的等体会到了再总结。

  再看一个比较器的例子,按照传统的写法,如下:

  Integer[]a={1,8,3,9,2,0,5};

  Arrays.sort(a,newComparator(){

  @Override

  publicintcompare(Integero1,Integero2){

  returno1-o2;

  }

  });

  Lambda表达式写法如下:

  Integer[]a={1,8,3,9,2,0,5};

  Arrays.sort(a,(o1,o2)->o1-o2);

  JDK中的函数式接口

  为了现有的类库能够直接使用Lambda表达式,Java8以前存在一些接口已经被标注为函数式接口的:

  java.lang.Runnable

  java.util.Comparator

  java.util.concurrent.Callable

  java.io.FileFilter

  java.security.PrivilegedAction

  java.beans.PropertyChangeListener

  Java8中更是新增加了一个包java.util.function,带来了常用的函数式接口:

  Function-函数:输入T输出R

  BiFunction-函数:输入T和U输出R对象

  Predicate-断言/判断:输入T输出boolean

  BiPredicate-断言/判断:输入T和U输出boolean

  Supplier-生产者:无输入,输出T

  Consumer-消费者:输入T,无输出

  BiConsumer-消费者:输入T和U无输出

  UnaryOperator-单元运算:输入T输出T

  BinaryOperator-二元运算:输入T和T输出T

  另外还对基本类型的处理增加了更加具体的函数是接口,包括:BooleanSupplier,DoubleBinaryOperator,DoubleConsumer,DoubleFunction,DoublePredicate,DoubleSupplier,DoubleToIntFunction,DoubleToLongFunction,DoubleUnaryOperator,IntBinaryOperator,IntConsumer,IntFunction,IntPredicate,IntSupplier,IntToDoubleFunction,IntToLongFunction,IntUnaryOperator,LongBinaryOperator,LongConsumer,LongFunction,LongPredicate,LongSupplier,LongToDoubleFunction,LongToIntFunction,LongUnaryOperator,ToDoubleBiFunction,ToDoubleFunction,ToIntBiFunction,ToIntFunction,ToLongBiFunction,ToLongFunction。结合上面的函数式接口,对这些基本类型的函数式接口通过类名就能一眼看出接口的作用。

  创建函数式接口

  有时候我们需要自己实现一个函数式接口,做法也很简单,首先你要保证此接口只能有一个函数操作,然后在接口类型上标注注解@FunctionalInterface即可。

  类型推导

  类型推导是Lambda表达式的基础,类型推导的过程就是Lambda表达式的编译过程。以下面的代码为例:

  FunctionstrToInt=str->Integer.parseInt(str);

  编译期间,我理解的类型推导的过程如下:

  先确定目标类型Function

  Function作为函数式接口,其方法签名为:Integerapply(Stringt)

  检测str->Integer.parseInt(str)是否与方法签名匹配(方法的参数类型、个数、顺序和返回值类型)

  如果不匹配,则报编译错误

  这里的目标类型是关键,通过目标类型获取方法签名,然后和Lambda表达式做出对比。

  方法引用

  方法引用(MethodReference)的基础同样是函数式接口,可以直接作为函数式接口的实现,与Lambda表达式有相同的作用,同样依赖于类型推导。方法引用可以看作是只调用一个方法的Lambda表达式的简化。

  方法引用的语法为:Type::methodName或者instanceName::methodName,构造函数对应的methodName为new。

  例如上面曾用到例子:

  FunctionstrToInt=str->Integer.parseInt(str);

  对应的方法引用的写法为

  FunctionstrToInt=Integer::parseInt;

  根据方法的类型,方法引用主要分为一下几种类型,构造方法引用、静态方法引用、实例上实例方法引用、类型上实例方法引用等

  构造方法引用

  语法为:Type::new。如下面的函数为了将字符串转为数组

  方法引用写法

  FunctionstrToInt=Integer::new;

  Lambda写法

  FunctionstrToInt=str->newInteger(str);

  传统写法

  FunctionstrToInt=newFunction(){

  @Override

  publicIntegerapply(Stringstr){

  returnnewInteger(str);

  }

  };

  数组构造方法引用

  语法为:Type[]::new。如下面的函数为了构造一个指定长度的字符串数组

  方法引用写法

  FunctionfixedArray=String[]::new;

  方法引用写法

  FunctionfixedArray=length->newString[length];

  传统写法

  FunctionfixedArray=newFunction(){

  @Override

  publicString[]apply(Integerlength){

  returnnewString[length];

  }

  };

  静态方法引用

  语法为:Type::new。如下面的函数同样为了将字符串转为数组

  方法引用写法

  FunctionstrToInt=Integer::parseInt;

  Lambda写法

  FunctionstrToInt=str->Integer.parseInt(str);

  传统写法

  FunctionstrToInt=newFunction(){

  @Override

  publicIntegerapply(Stringstr){

  returnInteger.parseInt(str);

  }

  };

  实例上实例方法引用

  语法为:instanceName::methodName。如下面的判断函数用来判断给定的姓名是否在列表中存在

  Listnames=Arrays.asList(newString[]{"张三","李四","王五"});

  PredicatecheckNameExists=names::contains;

  System.out.println(checkNameExists.test("张三"));

  System.out.println(checkNameExists.test("张四"));

  类型上实例方法引用

  语法为:Type::methodName。运行时引用是指上下文中的对象,如下面的函数来返回字符串的长度

  FunctioncalcStrLength=String::length;

  System.out.println(calcStrLength.apply("张三"));

  Listnames=Arrays.asList(newString[]{"zhangsan","lisi","wangwu"});

  names.stream().map(String::length).forEach(System.out::println);

  又比如下面的函数已指定的分隔符分割字符串为数组

  BiFunctionsplit=String::split;

  String[]names=split.apply("zhangsan,lisi,wangwu",",");

  System.out.println(Arrays.toString(names));

  Stream对象

  概念

  什么是Stream?这里的Stream不同于io中的InputStream和OutputStream,Stream位于包java.util.stream中,也是java8新加入的,Stream只的是一组支持串行并行聚合操作的元素,可以理解为集合或者迭代器的增强版。什么是聚合操作?

  Stream的几个特征:

  单次处理。一次处理结束后,当前Stream就关闭了。

  支持并行操作

  常见的获取Stream的方式

  从集合中获取

  Collection.stream();

  Collection.parallelStream();

  静态工厂

  Arrays.stream(array)

  Stream.of(T…)

  IntStream.range()

  这里只对Stream做简单的介绍,下面会有具体的应用。要说Stream与Lambda表达式有什么关系,其实并没有什么特别紧密的关系,只是Lambda表达式极大的方便了Stream的使用。如果没有Lambda表达式,使用Stream的过程中会产生大量的匿名类,非常别扭。

  举例

  以下的demo依赖于Employee对象,以及由Employee对象组成的List对象。

  publicclassEmployee{

  privateStringname;

  privateStringsex;

  privateintage;

  publicEmployee(Stringname,Stringsex,intage){

  super();

  this.name=name;

  this.sex=sex;

  this.age=age;

  }

  publicStringgetName(){

  returnname;

  }

  publicStringgetSex(){

  returnsex;

  }

  publicintgetAge(){

  returnage;

  }

  @Override

  publicStringtoString(){

  StringBuilderbuilder=newStringBuilder();

  builder.append("Employee{name=").append(name).append(",sex=").append

开班信息

开班课程 人数 了解详情
名企定向班 剩余名额3
ACCP8.0软件班 剩余名额8
短期冲刺班 剩余名额2
项目精英班 剩余名额1
NET重点班 剩余名额6
软件开发精英班 剩余名额2
JAVA特招班 剩余名额10

免费试听

试听课程 了解详情
名企定向班
ACCP8.0软件班
短期冲刺班
项目精英班
NET重点班
软件开发精英班
JAVA特招班

姓名:

电话:

最新就业

姓名 就业岗位 就业企业
占乐乐 软件工程师 关务通网络科技公司
张浩峰 软件工程师 嘉域网络科技有限公司
卜锡龙 软件工程师 必应科技有限公司
梁嘉嘉 软件工程师 林氏木业
何伟煊 java工程师 金政信息科技
张雅涵 NET工程师 国贸集团股份有限公司
张默 项目组长 极宇舟天有限公司
张婧涵 NET工程师 大族激光有限公司
张洪文 NET工程师 诚迈科技有限公司
王玥婷 java技术顾问岗位 百纳威尔有限公司
王鸿轩 Java开发岗位 爱卡智能
邓安志 美的集团
何浚宏 东和科技有限公司
黄隆 建发股份公司
刘应琴 国美集团
刘雨林 java工程师 唯品会科技有限公司
彭子昂 Java开发 爱卡智能有限公司

在线答疑更多++

  • 快8彩票平台

  • 快8彩票平台

  • 快8彩票平台

热门专题更多++

  • 佛山华大校区
  • 厦门华大职业教育
  • 福州华大IT学院
  • 厦门课工场
  • 北大青鸟佛山华大校区
  • 地址:广东省佛山市禅城区佛山大道北143号
  • 乘车路线:张槎路口站、白燕公园站、轻工路口站、金沙新城南门站
  • 招生电话:0757-88726000    4006-989-522
  • 网址:
  • 北大青鸟厦门华大职业皎月学院
  • 地址:厦门市集美区天阳路1-7号
  • 乘车路线:孙厝、永祥花园、第二医院、霞梧路口站
  • 招生电话:0592-5920811    4000-470-150
  • 网址:
  • 福州华大IT学院
  • 地址:福州市仓山区北园路122号
  • 乘车路线:白湖亭站、下濂站、埔垱站
  • 招生电话:0591-87880522    400-9966-370
  • 网址:
  • 北大青鸟厦门课工场
  • 地址:厦门市集美区天阳路1-7号
  • 乘车路线:孙厝、永祥花园、第二医院、霞梧路口站
  • 招生电话:0592-5920811    4000-470-150
  • 网址:
  • 技术支持:
  • 备案号:
  • 版权所有:佛山市禅城区华大计算机职业技能培训学校

北大青鸟华大校区微信公众平台

北大青鸟华大校区收款码