Lambda表达式--Java8的新功能案例详解(1)

1.lambda表达式--背景知识以及相关评价:

lambda表达式允许你通过表达式来代替功能接口。

函数编程在C#、Python、JavaScript中都得到充分体现。而Java直到最新的Java 8才开始正式支持函数编程,最明显的改进就是对Lamba表达式的支持。正如C#之父Anders Hejlsberg在那篇文章 编程语言大趋势 中所讲,未来的编程语言将逐渐融合各自的特性,而不存在单纯的声明式语言(如之前的Java)或者单纯的函数编程语言。将来声明式编程语言借鉴函数编程思想,函数编程语言融合声明式编程特性...这几乎是一种必然趋势。

当今世界主流编程语言无不吸纳强大的闭包概念,但有个例外,它就是Java。数年来,Java语言中增加闭包特征的工作看起来毫无进展。

早在15年之前,Scala语言和TypeSafe框架的作者Martin Odersky和Phillip Wadler发布了实验性的“Pizza”项目,由此,人们开始试图将闭包纳入编程语言的基本特征之一。尽管这看起来有点过于复杂,Java社区大概在2008年就有了接纳闭包概念的想法。但由于Oracle对Sun微系统公司的匆忙收购,Java被冷落,Java语言新版本的发布不断的被推迟。

但在Java8中,事情有了很大的变化,Java语言终于为Java编程部队配备了闭包的武器。“也许这是Java编程语言有史以来最重要的一次升级,”Oracle的Java语言架构师Brian Goetz说。他指出,在Java中引入闭包概念对Java程序开发方法的影响甚至会大于Java5中引入的泛型特征对编程方式带来的影响。“就像泛型能使开发人员对数据类型进行抽象,Lambda的目的是让程序员能够对程序行为进行抽象。”

Lambda这个名称来自于把闭包绑定到Java编程语言的Lambda项目。Lambda以及闭包的引入能做些什么?你可以这样想,它能够让程序员把一段程序代码当做数据一样使用。一个方法可以像定义和使用一个变量那样的方式被定义和使用,定义出的方法可以被当作参数传递到其它方法内,就像它们是一个对象实例或一个类型数据一样。“看起来这好像也没什么,但实际上它影响巨大,”Goetz说。“这将从根本上改变我们开发java程序的方式。”

我们等待了太久,但随着Java8的发布,Lambda终于成为Java规格说明书里的正式特征之一。一种由于过于复杂而最初被传统程序员放弃的语法将最终成为一种每个现代Java应用程序里都能看到的标准技术。

2.lambda表达式--基础语法以及使用细节:

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

Lambda表达式代替匿名内部类创建对象时,Lambda表达式的代码块将会代替实现抽象方法的方法体,Lambda表达式就相当于一个匿名方法。Lambda表达式的主要作用就是代替匿名内部类的繁琐语法。

*例如有如下的操作数组的接口和类:

//处理行为接口
public interface Command
{
	//封装处理行为的方法
	void process(int[] target);
}
//处理数组的类
public class ProcessArray
{
	//方法参数为处理的数组和处理命令
	public void process(int[] target,Command cmd)
	{
		cmd.process(target);
	}
}
//打印处理实现处理接口
public class PrintCommand implements Command
{
	public void process(int[] target)
	{
		for(int temp : target)
			System.out.println("迭代输出目标数组的元素:"+temp+"\t");
	}
}
//求和处理实现处理接口
public class AddCommand implements Command
{
	public void process(int[] target)
	{
		int sum=0;
		for(int temp : target)
			sum+=temp;
			System.out.println("目标数组求和的结果为:"+sum+"\t");
	}
}

Java8之前使用匿名内部类的解决方法:

//使用匿名对象和 匿名内部类实现
public class CommandTest
{
	public static void main(String[] args)
	{
		ProcessArray pa=new ProcessArray();
		int[] target={5,1,0,9,-2,10};

		//创建匿名对象
		pa.process(target,new PrintCommand());
		pa.process(target,new AddCommand());
		//调用处理数组的方法,具体行为取决于匿名内部类
		pa.process(target,new Command()
			{
				public void process(int[] target)
				{
					for(int temp : target)
						System.out.println("迭代输出目标数组的元素:"+temp+"\t");
				}
			}
		);
		pa.process(target,new Command()
			{
				public void process(int[] target)
				{
					int sum=0;
					for(int temp : target)
						sum+=temp;
					System.out.print("目标数组求和的结果为:"+sum+"\t");
				}
			}
		);
	}
}

Java8提供的Lambda表达式避免了使用内部类的繁琐语法:

//利用java8的Lambda表达式
public class CommandTest2
{
	public static  void main(String[] args)
	{
		ProcessArray pa=new ProcessArray();
		int[] target={5,1,0,9,-2,10};
		//处理数组,具体行为取决于内部类
		pa.process(target,(int[] arr)->
		{
			int sum=0;
			for(int tmp:target)
				sum+=tmp;
		    System.out.println("数组元素和为"+sum);
		}
		);
	}
}

Lambda表达式由3部分组成:

<1>形参列表。形参列表允许省略形参类型,如果形参列表只有一个参数,形参列表的圆括号也可以省略。

<2>箭头(->)。

<3>代码块。如果代码块只有一条语句,Lambda表达式允许省略代码的花括号;Lambda代码块只有一条return语    句,可以省略return关键字。

例如如下一个完整实例演示了 Lambda表达式的简化用法:

interface Eatable
{
	void taste();
}
interface Flyable
{
	void fly(String weather);
}
interface Addable
{
	int add(int a,int b);
}
public class LambdaDemo
{
	//调用该方法需要Eatable对象
	public void eat(Eatable v)
	{
		System.out.println(v);
		v.taste();
	}
	//调用该方法需要Flyable对象
	public void fly(Flyable v)
	{
		System.out.println(v);
		v.fly("天气晴朗,万里无云");
	}
	//调用该方法需要Addable对象
	public void add(Addable v)·
	{
		System.out.println(v);
		System.out.println("5和3的和:"+v.add(5,3));
	}
	public static void main(String[] args)
	{
		LambdaDemo ld=new LambdaDemo();
		//Lambda表达式只有一条语句,可以省略花括号
		ld.eat(()->System.out.println("好吃!"));
		//Lambda表达式的形参列表只有一个形参,可以省略圆括号
		ld.fly(weather->
		{
			System.out.println("今天的天气是"+weather);
		}
		);
		//Lambda表达式只有一条语句,可以省略花括号,当需要返回值时,也可以省略return关键字
		ld.add((a,b)->a+b);
	}
}

Lambda表达式的类型,也被称为目标类型(Target Type),Lambda表达式的目标类型必须是函数式接口。    函数式接口(Functional Interface)代表只包含一个抽象方法的接口,函数式接口可以有多个类方法和默认方法。java8开始提供的注释(Annotation)中的@FunctionalInterface注解,就是用于提示编译器进行函数式接口的检查。

Java预定义了大量的函数式接口,例如Runnable、ActionListenner都是函数式接口,还有java.util.function包下也有大量的函数式接口。(Package java.util.function

Functional interfaces provide target types for lambda expressions and method references)

例如该包下典型的包含以下四类接口:

<1>XxxFunction:这类接口通常用于对指定数据进行转换处理。通常包含一个apply抽象方法,该方法对参数进行处理转换,然后返回一   个新的值,例如DoubleToIntFunction 的applyAsInt方法(DoubleToIntFunctionDemo.java演示 ) 。

<2>XxxConsumer:该接口通常包含一个apply抽象方法,与XxxFunction接口类似,只是没有返回值。

<3>XxxPredicate:这类接口通常包含一个test()抽象方法,该方法通常用来对参数进行某种判断,用于进行筛滤数据,然后返回一个布尔值,

<4>XxxSupplier:这类接口通常包含一个getAsXxx()抽象方法,该方法不需要参数,该方法会按照某种逻辑算法返回一个数据。

例如java.util.function包下的DoubleToIntFunction接口的用法如下:

import java.util.function.*;
public class DoubleToIntFunctionDemo
{
	public void DoubleToInt(double d,DoubleToIntFunction dti)
	{
		int tmp=dti.applyAsInt(d);
		System.out.println(d+"----->"+tmp);
	}
	public static void main(String[] args)
	{
		DoubleToIntFunctionDemo a=new DoubleToIntFunctionDemo();
		a.DoubleToInt(1.20,(d)->
		{
			return (int)d;
		}
		);
	}
}

这里只是利用几个简单的例子介绍了java的Lambda表达式,以后还会有持续更新,希望从事开发的朋友能够多多交流,不断进步!

时间: 2024-09-29 03:28:18

Lambda表达式--Java8的新功能案例详解(1)的相关文章

Microsoft PowerPoint文件管理控件Aspose.Slides新功能示例详解——支持字体回退

Aspose.Slides for .NET是独特的演示处理API,使应用程序能够读取,编写,修改和转换PowerPoint演示文稿.作为独立的API,它提供了管理PowerPoint关键功能的功能,例如管理文本,形状,表格和动画,向幻灯片添加音频和视频,预览幻灯片等等. 近期,Aspose.Slides for .NET更新至最新版v19.10,现在有一些非常有趣且实用的功能值得为大家讲解一下,比如新增支持字体回退,以及在占位符中设置提示文本,接下来通过一些简单的示例来为大家说明一下! 支持字

ios新特征 ARC详解

IOS ARC 分类: IOS ARC2013-01-17 09:16 2069人阅读 评论(0) 收藏 举报 目录(?)[+] 关闭工程的ARC(Automatic Reference Counting) 顺带附上ARC教程 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流和讨论.请不要将本文的部分或全部内容用于商用,谢谢合作. 欢迎转载本文,但是转载请注明本文出处:http://www.onevcat.com/2012/06/arc-hand-by

(转载)C语言单链表实现19个功能完全详解

最近在复习数据结构,想把数据结构里面涉及的都自己实现一下,完全是用C语言实现的. 自己编写的不是很好,大家可以参考,有错误希望帮忙指正,现在正处于编写阶段,一共将要实现19个功能.到目前我只写了一半,先传上来,大家有兴趣的可以帮忙指正,谢谢 在vs2010上面编译运行无错误. 每天都会把我写的新代码添加到这个里面.直到此链表完成. #include "stdafx.h" #include "stdio.h" #include <stdlib.h> #in

新辰:详解首页被K后SEOer必做的三大排除方法!

近段时间,有很多朋友向新辰抱怨说出大问题了,为神马site不到首页了,而且收录变成了0?唉,新辰不得不很同情的告诉你:你的首页真的被K了!好了,作为一个职业SEOer,面对被K犹如已经看破红尘般没了脾气,所以,废话少说,身为SEOer的你赶紧补救吧!希望新辰的这些方法能够帮助你早日逃离拔毛的痛苦哦: 所谓治病先察言观色,后开方救人,新辰说的就是先找准病因,才能给出解决的办法.面对突然site不到首页的情况,请先保持冷静哦,然后需要先查看一下收录和排名怎么样了,索引量如何,蜘蛛日志的返回代码是多少

IOS-TextField功能方法详解

//初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 130, 30)]; //设置边框样式,只有设置了才会显示边框样式 text.borderStyle = UITextBorderStyleRoundedRect; typedef enum { UITextBorderStyleNone, UITextBorderStyleLine, UITextBord

【甘道夫】通过Mahout构建贝叶斯文本分类器案例详解

http://acm.hdu.edu.cn/showproblem.php?pid=1507 大致题意:在一个n*m的格子上,黑色的地方不可用,问在白色格子上最多可放多少1*2的矩阵. 思路:建图,每个白色格子与它临近的上下左右的白色格子建边,求最大匹配,答案为最大匹配/2,因为是双向图.最后输出匹配边时,当找到一组匹配边记得将该边标记,以防重复计算. #include <stdio.h> #include <algorithm> #include <set> #inc

HP电脑的增霸卡功能操作详解

机房管理中HP电脑的增霸卡功能操作详解 一.软件去除保护 1).电脑开机后等待进入增霸卡选择系统界面: 2).按F1帮助,F10进入增霸卡BIOS界面: 3).光标切换到>>>系统还原模式,模式有:(不保护.每次.周.月.),选择不保护:(如果第四步可操作,则省略这一步操作) 4).光标切换到>>>磁盘工具,选择要进行操作的系统的启动盘,选择保护模式,模式有:(保护.不保护),选择"不保护":(如果保护模式不可操作,则进行第三步操作) 5).保存,重

str_replace函数的使用规则和案例详解

str_replace函数的使用规则和案例详解 str_replace函数的简单调用: <?php $str = '苹果很好吃.'; //请将变量$str中的苹果替换成香蕉 $strg = str_replace('苹果','香蕉',$str); echo $strg; ?> 输出结果为:"香蕉很好吃" 解释:在str中将"苹果"替换成"香蕉", 所以原本的$str"苹果很好吃" 被改成了 "香蕉很好吃&

【强化学习篇】--强化学习案例详解一

一.前述 本文通过一个案例来讲解Q-Learning 二.具体 1.案例 假设我们需要走到5房间. 转变为如下图:先构造奖励,达到5,即能够走得5的action则说明奖励比较高设置成100,没有达到5说明奖励比较低,设置成0. Q-learning实现步骤:  2.案例详解: 第一步的Q(1,5):最开始的Q矩阵都是零矩阵,迭代完之后Q(1,5)是100 第二次迭代:依旧是随机 收敛的意思是最后Q基本不变了,然后归一化操作,所有值都除以500,然后计算百分比. 则最后的分值填充如下: 原文地址: