【Lambda表达式概述】

Lambda表达式支持将代码块作为方法参数,Lambda表达式允许将使用简洁的代码来创建只有一个抽象方法的接口的实例。(这种接口称为函数式接口

【入门实例】

package com.Higgin.Lambda;

import org.junit.Test;

interface Command{
//接口里定义的process封装行为
public void process(int[] target);
} class ProcessArray{
public void process(int[] target , Command cmd){
cmd.process(target);
}
} public class LambdaDemo { /**
* Lambda的方式 代替匿名内部类
*/
public static void main(String[] args) {
ProcessArray pa=new ProcessArray();
int[] array={1,2,3,4,5};
pa.process(array, (int[] target)->{
int sum=0;
for(int tmp:target){
sum=sum+tmp;
}
System.out.println("数组的和为"+sum);
});
} /**
* 匿名内部类的方式
*/
@Test
public void test(){
ProcessArray pa=new ProcessArray();
int[] array={1,3,5,7,9};
pa.process(array, new Command() {
@Override
public void process(int[] target) {
int sum=0;
for(int tmp:target){
sum=sum+tmp;
}
System.out.println("数组的和为"+sum);
}
});
}
}

【分析】

int sum=0;
for(int tmp:target){
sum=sum+tmp;
}
System.out.println("数组的和为"+sum);

lambda表达式代码 与 创建匿名内部类 时需要实现的process(int[] target)方法完全一致。

Lambda表达式不需要去实现 " new XXX(){} " 这部分繁琐的代码。

lambda表达式不需要指出重写的方法名字

lambda表达式不需要重写方法的返回值类型—— 只需要给出重写的方法括号以及括号里的形参列表 即可。

【Lambda表达式的组成】

Lambda的主要作用是代替匿名内部类的繁琐语法。其组成如下:

1.形参列表。形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。

2.箭头(->)。

3.代码块。

如果代码块只有一条语句,可以省略代码的花括号,此时也得该语句后面的分号。

如果代码块只有一条return语句,甚至可以忽略return关键字。

【简单的几个例子】

package com.Higgn.Lambda;

interface Eateable{
void eat();
} interface Flyable{
void fly(String weather);
} interface Addable{
int add(int a,int b);
} class Demo{
//调用Eateable对象的方法
public void getEat(Eateable e){
e.eat();
}
//调用Flyable的fly方法
public void getFly(Flyable f){
f.fly("晴天");
}
//调用Addable的add方法
public void getAdd(Addable a){
System.out.println("和为:"+a.add(10,8));
}
} public class LambdaDemo {
public static void main(String[] args) {
Demo demo=new Demo(); System.out.println("--------------------分割线1---------------------------"); /**
* 无参数、代码块有两条及以上语句
*/
demo.getEat(()->{
System.out.println("吃了一个大苹果");
System.out.println("又吃了一个大橘子");
}); System.out.println("--------------------分割线2---------------------------"); /**
* 无参数、代码块只有一条语句
* 此时可以忽略花括号、分号
*/
demo.getEat(()->System.out.println("只吃一个大西瓜!")); System.out.println("--------------------分割线3---------------------------"); /**
* 形参列表有一个参数、代码块只有一条语句
*/
demo.getFly((weather)->{
System.out.println("今天天气是:"+weather);
}); System.out.println("--------------------分割线4---------------------------"); /**
* 形参列表只有一个参数、代码块只有一条语句
* 可以省略参数的圆括号,可以省略代码块的花括号
*/
demo.getFly(weather->System.out.println("明天天气是:"+weather)); System.out.println("--------------------分割线5---------------------------"); /**
* 形参列表有两个参数,有返回值
*/
demo.getAdd((a,b)->{
return a+b;
}); System.out.println("--------------------分割线6---------------------------"); /**
* 形参列表有两个参数,有返回值
* 代码块中只有一条语句,即使该表达式需要返回值,也可以省略return语句
*/
demo.getAdd((a,b)->a+b);
}
}

【运行结果】

【Lambda表达式与函数式接口】

函数式接口:代表只包含一个抽象方法接口。函数式接口可以包含多个默认方法、类方法,但是只能声明一个抽象方法。

Lambda表达式的目标类型(target type)必须是函数式接口(functional interface)。

@FunctionalInterface

Java8专门为函数式接口提供了@FunctionalInterface注解,该注解对程序功能没有任何作用。它用于告诉编译器执行更严格检查,检查该接口必须是函数式接口,否则报错。

Runnable是java本身提供的一个函数式接口

【Runnable使用Lambda表达式实现】

/**
* Runnable接口中只包含一个无参数的方法
* Lambda表达式代表的匿名方法实现了Runnable接口中唯一的、无参数的方法
* 因此下面的Lambda表达式创建了一个Runnable对象
*/

public static void main(String[] args) {
//Runnable是一个函数式接口
Runnable r=()->{
for(int i=0;i<100;i++){
System.out.println("i======"+
i);
}
};

Thread t=new Thread(r);
t.start();
}

【Lambda表达式的两个限制】

1.Lambda表达式的目标类型必须是明确的函数式接口。

2.Lambda表达式只能为函数式接口创建对象,Lambda表达式只能实现一个方法,因此只能为只有一个抽象方法的接口(函数式接口)创建对象。

【保证Lambda表达式的目标类型是一个明确的函数式接口的三种方式】

1.将Lambda表达式赋值给函数式接口类型的变量。

2.将Lambda表达式作为函数式接口类型的参数传给某个方法。

3.使用函数式接口对Lambda表达式进行强制类型转换。

【保证函数式接口的方法】

【Java8的典型4类函数接口】

Java8在java.util.function包下预定义了大量的函数式接口,典型的4类接口如下:

1.XxxFunction接口:通常包含一个apply()抽象方法。该方法用于对参数进行处理、转换(apply()方法的处理逻辑由Lambda表达式实现),然后返回一个新的值。该函数式接口常用于对指定数据的转换。

2.XxxConsumer接口:通常包含一个accept()抽象方法,与上面的apply()方法类似,主要负责对数据的处理,区别是accept()方法不会返回处理结果。

3.XxxPredicate接口:通常包含一个test()抽象方法,该方法常用于对参数进行某种判断(test()方法的判断逻辑由Lambda表达式实现),然后返回一个boolean值。该函数式接口通常用于判断参数是否满足特定条件,常用于数据的筛选。

4.XxxSupplier接口:通常包含一个getAsXxx()抽象方法,该方法不需要输入参数,该方法会按照某种逻辑算法(getAsXxx()方法的逻辑算法由Lambda表达式来实现)返回一个数据。

方法引用构造器引用

如果Lambda表达式的代码块只有一条代码,程序可以省略Lambda表达式中的代码块的花括号。

除此之外,如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用构造器引用

【Lambda表达式支持的方法引用和构造器引用】

方法引用构造器引用都需要使用两个英文冒号“::”

【种类一:引用类方法】

/**
* 类方法引用,也就是调用Integer类的valueOf()方法来实现函数式接口Converter中唯一的抽象方法convert(String str),
* 当调用convert(String str)方法时,调用参数将会传递给Integer类的ValueOf()方法。
*/ @FunctionalInterface
interface Converter{
//convert方法:String类型转换为Integer类型
Integer convert(String str);
} public class ConverterDemo {
public static void main(String[] args) {
/**
* Lambda表达式的方式实现
*/
Converter con1=str->Integer.valueOf(str); // (a,b...)->类名.类方法(a,b...)
Integer val1=con1.convert("666");
System.out.println(val1); /**
* 引用类方法
* 使用 方法引用 代替Lambda表达式
* 函数式接口中被实现的方法的全部参数传给该类方法作为参数
*/
Converter con2=Integer::valueOf; //类名::类方法
Integer val2=con2.convert("888");
System.out.println(val2);
}
}

【种类二:引用特定对象的实例方法】

/**
* 引用特定对象的实例方法
* 下面案例也就是调用"ABCDEFGHIGK"对象的实例方法indexOf()来实现Converter函数式接口中唯一的抽象方法convert(String str),
* 当调用convert(String str)方法时,调用的参数"D"会传递给"ABCDEFGHIGK"对象的实例方法indexOf()。
*/ @FunctionalInterface
interface Converter{
//convert方法:String类型转换为Integer类型
Integer convert(String str);
} public class ConverterDemo { public static void main(String[] args) {
/**
* Lambda表达式创建converter对象
*/
Converter con1=str->"ABCDEFGHIGK".indexOf(str); //(a,b...)->特定对象.实例方法(a,b...)
Integer val1=con1.convert("H");
System.out.println(val1); /**
* 引用特定对象的实例方法,代替Lambda表达式
     * 函数式接口中被实现方法的全部参数传给该类方法作为参数
*/
Converter con2="ABCDEFGHIGK"::indexOf; //特定对象::实例方法
Integer val2=con1.convert("D");
System.out.println(val2);
}
}

【种类三:引用某类对象的实例方法】

/**
* 引用某类对象的实例方法
*/ @FunctionalInterface
interface ISubString{
public String sub(String str,int begin,int end);
} public class SubStringDemo {
public static void main(String[] args) {
/**
* Lambda表达式方式
*/
ISubString is1=(str,begin,end)->str.substring(begin,end); //(a,b...)->a.实例方法(b...)
String str1=is1.sub("HigginCui", 6, 9);
System.out.println(str1); /**
* 引用某类对象的实例方法, 代替Lambda表达式
* 函数式接口中被实现方法的第一个参数"HigginCui"作为调用者,后面的参数全部传递给该方法作为参数
*/
ISubString is2=String::substring; //类名:实例方法
String str2=is2.sub("HigginCui", 0, 6);
System.out.println(str2);
}
}

【种类4:引用构造器】

@FunctionalInterface
interface MyTest{
JFrame win(String title);
} public class TestDemo {
public static void main(String[] args) {
/**
* Lambda的方式
*/
MyTest mt1=(String a)->new JFrame(a); //(a,b...)->new 类名(a,b...)
JFrame jf1=mt1.win("我的窗口1");
System.out.println(jf1); /**
* 引用构造器
*/
MyTest mt2=JFrame::new; //类名::new
JFrame jf2=mt2.win("我的窗口2");
System.out.println(jf2);
}
}

07_Java8新增的Lambda表达式的更多相关文章

  1. 【Java】Java8新增的Lambda表达式_学习笔记

    一.Lambda表达式可以简化创建匿名内部类对象 1.不需要new XXX(){}这种繁琐代码. 2.不需要指出重写的方法名. 3.不要给出重写的方法的返回值类型. 4.Lambda相当于一个匿名方法 ...

  2. Java 8新增的Lambda表达式

    一. 表达式入门 Lambda表达式支持将代码块作为方法参数,lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例,相当于一个匿名的方法. 1.1 La ...

  3. C++中对C的扩展学习新增语法——lambda 表达式(匿名函数)

    1.匿名函数基础语法.调用.保存 1.auto lambda类型 2.函数指针来保存注意点:[]只能为空,不能写东西 3.std::function来保存 2.匿名函数捕捉外部变量(值方式.引用方式) ...

  4. Java 8 Lambda表达式探险

    为什么?    我们为什么需要Lambda表达式    主要有三个原因:    > 更加紧凑的代码      比如Java中现有的匿名内部类以及监听器(listeners)和事件处理器(hand ...

  5. 【转载】C++ function、bind和lambda表达式

    本篇随笔为转载,原贴地址:C++ function.bind和lambda表达式. 本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制 ...

  6. Java 8 Lambda表达式

    Java 8 Lambda表达式探险 http://www.cnblogs.com/feichexia/archive/2012/11/15/Java8_LambdaExpression.html 为 ...

  7. 匿名方法,Lambda表达式,高阶函数

    原文:匿名方法,Lambda表达式,高阶函数 匿名方法 c#2.0引入匿名方法,不必创建单独的方法,因此减少了所需的编码系统开销. 常用于将委托和匿名方法关联,例如1. 使用委托和方法关联: this ...

  8. C++11 中function和bind以及lambda 表达式的用法

    关于std::function 的用法:  其实就可以理解成函数指针 1. 保存自由函数 void printA(int a) { cout<<a<<endl; } std:: ...

  9. Java :一文掌握 Lambda 表达式

    本文将介绍 Java 8 新增的 Lambda 表达式,包括 Lambda 表达式的常见用法以及方法引用的用法,并对 Lambda 表达式的原理进行分析,最后对 Lambda 表达式的优缺点进行一个总 ...

随机推荐

  1. CMD-NET命令详解(转载)

    本文转自http://www.cnblogs.com/chenjq0717/archive/2010/05/09/1730934.html net命令大全,net命令用法,net网络命令,net命令使 ...

  2. session 重写进入redis测试

    在实际业务中,当session存储过多 或者操作频繁,业务逐渐扩展的时候,文件存储已经无法满足session操作速度和需求,可以考虑用数据库或者nosql的redis来存储session,本文讲解如何 ...

  3. xampp配置host和httpd可以随意访问任何本机的地址

    1.修改host 不管你用的是什么系统,windows, mac,电脑上都会有一个 hosts 文件,修改这个文件,可以改变主机名所对应的 ip 地址.比如你安装了 Web 开发环境(MAMP 或 W ...

  4. gmt学习资源

    1 http://seisman.info/ http://examples.gmt-china.org/ http://docs.gmt-china.org http://modules.gmt-c ...

  5. 基础数据结构 之 树(python实现)

    树是数据结构中常用到的一种结构,其实现较栈和队稍为复杂一些.若树中的所有节点的孩子节点数量不超过2个,则该为一个二叉树.二叉树可用于查找和排序等.二叉树的主要操作有:建树,遍历等.遍历是树中的一个最为 ...

  6. 【50】了解new和delete的合理替换时机

    1.有时候,我们替换掉编译器提供的new或者delete.首先思考,为什么想要替换?下面是三个常见理由: a.用来检测运用上的错误,超额分配一些内存,再额外的空间放置一些内存: b.为了强化效能,编译 ...

  7. 关于自定义adapter使用getApplicationContext()影响主题

    最近弄了一个东西,listview+switch构成界面 关于android自定义adapter,继承自baseadapter,发现界面的switch开关主题变了想要的是浅色的主题,但是却发现变成了深 ...

  8. [转]Log4Net中配置文件的解释

    FROM:http://www.cnblogs.com/kissazi2/p/3392605.html 一个完整的配置文件的例子如下所示 <log4net> <!-- 错误日志类-- ...

  9. Java基础 Day14 泛型

    //为什么要使用泛型 //1.解决元素存储的安全性的问题 //2.解决获取元素时,须要类型转换的问题 //未使用泛型 package org.tizen.test; import java.util. ...

  10. What is a heap?--reference

    A heap is a partially sorted binary tree. Although a heap is not completely in order, it conforms to ...