您的位置:首页 > 编程语言 > Java开发

Java8特性总结(二)Lambda表达式,函数式接口,方法引用

2017-01-19 09:44 1281 查看

导航

Java8特性总结(一)概述

Java8特性总结(二)Lambda表达式,函数式接口,方法引用

Java8特性总结(三)接口方法,注解,日期,Base64

前言

这三个新特性使用的时候关系就很紧密,所有打算用这篇文章详细介绍一下。

特别是Lambda表达式和函数式接口,简直就是密不可分。

Lambda表达式

Lambda表达式的特点就是简介优雅(省代码)。

Lambda表达式很多语言都支持,Java程序员一直在要求Java也要加入这个功能,终于Java8提供了这个功能,使Java8成为继Java5后,变更最大的版本。

Lambda百度百科定义

“Lambda 表达式”

(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

目前主流语言都支持Lambda:Java,C#,C++,Python,JavaScript等。

闭包百度百科定义

闭包(closure)是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。

“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。

在PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。

来一个开胃菜

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ));


请注意参数e的类型是由编译器推测出来的。同时,你也可以通过把参数类型与参数包括在括号中的形式直接给出参数的类型:

forEach的定义

interface Iterable<T>
{
default void forEach(Consumer<? super T> action)
{
for (T t : this)
{
action.accept(t);
}
}
}


e -> System.out.println( e )


的等价代码如下

new Consumer<String>()
{
void accept(String t)
{
System.out.println( e );
}
}


因为forEach的参数是Consumer,而Consumer又是函数接口,因此可以直接用Lambda进行表示。

这样写也可以

Arrays.asList( "a", "b", "d" ).forEach( (String e) -> System.out.println( e ) );


这样写也可以

Arrays.asList( "a", "b", "d" ).forEach( (String e) -> {
System.out.println( e );
});


后一种情况一般是代码较多的时候使用。

lambda表达式是可以访问局部变量的,这样局部变量就变成fianl了,不可以进行修改的。

下面两段代码是一个意思。

String sp="-";
Arrays.asList( "a", "b", "d" ).forEach( (e) ->System.out.println( e+sp ));




final String sp="-";
Arrays.asList( "a", "b", "d" ).forEach( (e) ->System.out.println( e+sp ));


可以读写静态变量和属性。

class LambdaTest
{
static int staticNum;
int num;

void testScopes()
{
Function<Integer, String> testFunc= (from) -> {
num= 2;
staticnum=1;
return String.valueOf(staticNum+num+from);
};
}
}


函数式接口

到这里有人可能会问Lambda表达式如果有返回值怎么办?

好问题,因为Java8增加了很多函数式接口(在java.util.function包下的接口)

这里的函数式接口可以理解成,定义了很多不同的参数个数待实现接口。

接口方法参数返回值
FunctionR apply(T t)一个参数R
DoubleFunctionR apply(double value)一个参数R
IntFunctionR apply(int value)一个参数R
UnaryOperator extends FunctionT apply(T t)一个参数T
接口方法参数返回值
BiFunctionR apply(T t, U u)两个参数R
BinaryOperator extends BiFunctionT apply(T t, T u)两个参数T
DoubleBinaryOperatordouble applyAsDouble(double l, double r)两个参数double
DoubleBinaryOperatordouble applyAsDouble(double l, double r)两个参数double
DoubleUnaryOperatordouble applyAsDouble(double operand)一个参数double
IntBinaryOperatorint applyAsInt(int left, int right)两个参数int
LongBinaryOperatorlong applyAsLong(long left, long right)两个参数long
接口方法参数返回值
DoubleToIntFunctionint applyAsInt(double value)一个参数int
IntToLongFunctionlong applyAsLong(int value)一个参数long
DoubleToLongFunctionlong applyAsLong(double value)一个参数long
IntToDoubleFunctiondouble applyAsDouble(int value)一个参数double
接口方法参数返回值
Predicateboolean test(T t)一个参数boolean
BiPredicateboolean test(T t, U u)两个参数boolean
DoublePredicateboolean test(double value)一个参数boolean
IntPredicateboolean test(int value)一个参数boolean
接口方法参数返回值
SupplierT get()T
BooleanSupplierboolean getAsBoolean()boolean
DoubleSupplierdouble getAsDouble()boolean
IntSupplierint getAsInt()boolean
接口方法参数返回值
Consumervoid accept(T t)一个参数void
BiConsumervoid accept(T t, U u)两个参数void
DoubleConsumervoid accept(double value)一个参数void
IntConsumervoid accept(int value)一个参数void
ObjDoubleConsumervoid accept(T t, double value)两参数void
以上的列表是
java.util.function
包下面的部分函数式接口没有列全,大致可以分为以下几类。

Function<T, R>
BiFunction<T, U, R>
Predicate<T>
Supplier<T>
Consumer<T>


其他的都是Java自己实现的一些特例情况。

其他包下的

Runnable

Comparator

Callable

接下来对每个函数接口进行举例说明

Function

Function<T, R>
{
R apply(T t);
}


这个很好理解就是输入一个类型的参数,经过变换返回另外一个类型的对象。

代码示例:

Function<String, Integer> toInteger = Integer::valueOf;//方法引用
Function<String, String> backToString =toInteger.andThen(String::valueOf);//方法引用
backToString.apply("123");     // "123"


BiFunction

BiFunction<T, U, R>
{
R apply(T t, U u)
}


输入两个不同类型的参数,然后输出第三种类型的对象。

Predicate断言

Predicate<T>
{
boolean test(T t);
}


输入一个类型的参数,经过运算后输出一个boolean值。

代码示例:

Predicate<String> predicate = (s) -> s.length() > 0;
predicate.test("foo");              // true
predicate.negate().test("foo");     // false
Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();


Supplier提供者

Supplier<T>
{
T get();
}


这个用法一般是和默认的构造器进行绑定。

如:

Supplier<String> strSupplier=String::new;
String str=strSupplier.get();


每次get都会调用new String();

Consumer消费者

Consumer<T>
{
void accept(T t);
}


示例代码:

String str="Joy";
Consumer<String> consumer = (p) -> System.out.println("Hello, " + p);
consumer.accept(str);//消费一个String


Runnable

Runnable
{
public abstract void run()
}


这个实现和以前基本没有什么变化。

第一种形式

Runnable r=()->System.out.println();
new Thread(r).start();


最简单形式

new Thread(()->System.out.println()).start();


Comparator比较器

Comparator<T>
{
int compare(T o1, T o2);
}


实现比较方法,主要为排序使用的。

代码例子:

List<String> list=Arrays.asList("tom","bob","joy","joy");
list.sort((a,b)->a.compareTo(b));


怎么又没看见
Comparator
??

sort()
函数

default void sort(Comparator<? super E> c)


Callable

Callable<V>
{
V call() throws Exception;
}


执行一个操作,同时返回Callable声明的类型。

代码例子:

ExecutorService service=Executors.newFixedThreadPool(10);
Future<String> f=service.submit(()->"hello world");


方法引用

接下来说一下方法引用。

方法引用的例子我们在前面的代码已经使用了。

上面的例子:

Function<String, Integer> toInteger = Integer::valueOf;//方法引用
Function<String, String> backToString = toInteger.andThen(String::valueOf);//方法引用
backToString.apply("123");     // "123"


定义一个接口函数,与一个方法进行关联。

要求就是,参数返回值必须要保证一致。

例如上面的

Function<String,Integer>
方法的参数是String,返回值是Integer

Integer.valueOf
这个方法的参数是String,返回值是Integer

这样就可以关联了。

部分参考:

http://www.cnblogs.com/BigFeng/p/5204899.html?utm_source=tuicool&utm_medium=referral

http://baike.baidu.com/item/Lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F

http://baike.baidu.com/item/%E9%97%AD%E5%8C%85

https://yq.aliyun.com/articles/31514

http://blog.csdn.net/feilengcui008/article/details/45822173
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息