java8.Lambda表达式
2016-03-02 09:39
429 查看
转载自:http://www.jb51.net/article/48304.htm
http://www.oschina.net/translate/everything-about-java-8
[java] view
plain copy
List<Integer> list = Arrays.asList(7, 4, 1, 2);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return a > b ? 1 : (a == b) ? 0 : -1;
}
});
System.out.println(list);// [1, 2, 4, 7]
在Java 8 中就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:
[java] view
plain copy
Collections.sort(list, (Integer a, Integer b) -> {
return a > b ? 1 : (a == b) ? 0 : -1;
});
代码变得更段且更具有可读性,但是实际上还可以写得更短:
[java] view
plain copy
Collections.sort(list, (Integer a, Integer b) -> a > b ? 1 : (a == b) ? 0 : -1);
对于函数体只有一行代码的,可以去掉大括号{}以及return关键字,但是还可以写得更短点:
[java] view
plain copy
Collections.sort(list, (a, b) -> a > b ? 1 : (a == b) ? 0 : -1);
Java编译器可以自动推导出参数类型,所以可以不用再写一次类型。
当把经典风格java语法转变为Lambda表达式语法时,主要关注接口方法的参数和功能逻辑。
另外一个例子,如果打算写一个方法,此方法接收一个Lambda表达式作为参数,那么该怎么写?首先把方法参数声明成函数接口,然后才能传递Lambda表达式进来,如下所示:
[java] view
plain copy
interface Action {
void doThing(String param);
}
[java] view
plain copy
public void func(Action actor) {
actor.doThing("Hello World!");
}
如果想要调用func()方法,那么通常地做法,给func方法传递一个Action的匿名实现类。如下所示:
[java] view
plain copy
new LambdaTest().func(new Action() {
@Override
public void doThing(String param) {
System.out.println("Hi! " + param);
}
});
但是现在有函数接口做参数类型,所以可以用下面的方式调用func ():
[java] view
plain copy
new LambdaTest().func((String parm) -> {
System.out.println("Hi! " + parm);
});
甚至可以更简单:
[java] view
plain copy
new LambdaTest().func(parm -> System.out.println("Hi! " + parm));
[java] view
plain copy
public class Test {
public static void main(String[] args) {
Formula formula = new Formula() {
@Override
public double calculate(int a) {
return sqrt(a * 100);
}
};
System.out.println(formula.calculate(100)); // 100.0
System.out.println(formula.sqrt(16)); // 4.0
}
}
interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保接口一定达到这个要求,只需要给接口添加 @FunctionalInterface 注解,编译器如果发现标注了这个注解的接口有多于一个抽象方法的时候会报错的。
[java] view
plain copy
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
[java] view
plain copy
Converter<String, Integer> converter = (aa) -> Integer.valueOf(aa);
Integer converted = converter.convert("123");
System.out.println(converted); // 123
需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的。
JDK8中新增了一个包,java.util.function,这个包里有一些专门给新增的API使用的函数接口。
下面列出几个java.util.function中定义的接口:
[java] view
plain copy
public interface Consumer<T> : void accept(T t);//在T上执行一个操作,无返回结果
public interface Supplier<T> : T get();//无输入参数,返回T的实例
public interface Predicate<T> : boolean test(T t);// 输入参数为T的实例,返回boolean值
public interface Function<T, R> : R apply(T t);// 输入参数为T的实例,返回R的实例
方法引用:
静态方法引用: String::valueOf
非静态方法引用: Object::toString
继承的函数引用: x::toString
构造函数引用: ArrayList::new
方法引用 等价的lambda表达式
String::valueOf x -> String.valueOf(x)
Object::toString x -> x.toString()
x::toString () -> x.toString()
ArrayList::new () -> new ArrayList<>()
http://www.oschina.net/translate/everything-about-java-8
Lambda表达式
使用Java8之前的语法,如何实现比较器:[java] view
plain copy
List<Integer> list = Arrays.asList(7, 4, 1, 2);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return a > b ? 1 : (a == b) ? 0 : -1;
}
});
System.out.println(list);// [1, 2, 4, 7]
在Java 8 中就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:
[java] view
plain copy
Collections.sort(list, (Integer a, Integer b) -> {
return a > b ? 1 : (a == b) ? 0 : -1;
});
代码变得更段且更具有可读性,但是实际上还可以写得更短:
[java] view
plain copy
Collections.sort(list, (Integer a, Integer b) -> a > b ? 1 : (a == b) ? 0 : -1);
对于函数体只有一行代码的,可以去掉大括号{}以及return关键字,但是还可以写得更短点:
[java] view
plain copy
Collections.sort(list, (a, b) -> a > b ? 1 : (a == b) ? 0 : -1);
Java编译器可以自动推导出参数类型,所以可以不用再写一次类型。
当把经典风格java语法转变为Lambda表达式语法时,主要关注接口方法的参数和功能逻辑。
另外一个例子,如果打算写一个方法,此方法接收一个Lambda表达式作为参数,那么该怎么写?首先把方法参数声明成函数接口,然后才能传递Lambda表达式进来,如下所示:
[java] view
plain copy
interface Action {
void doThing(String param);
}
[java] view
plain copy
public void func(Action actor) {
actor.doThing("Hello World!");
}
如果想要调用func()方法,那么通常地做法,给func方法传递一个Action的匿名实现类。如下所示:
[java] view
plain copy
new LambdaTest().func(new Action() {
@Override
public void doThing(String param) {
System.out.println("Hi! " + param);
}
});
但是现在有函数接口做参数类型,所以可以用下面的方式调用func ():
[java] view
plain copy
new LambdaTest().func((String parm) -> {
System.out.println("Hi! " + parm);
});
甚至可以更简单:
[java] view
plain copy
new LambdaTest().func(parm -> System.out.println("Hi! " + parm));
接口的默认方法(default)
Java 8允许给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:[java] view
plain copy
public class Test {
public static void main(String[] args) {
Formula formula = new Formula() {
@Override
public double calculate(int a) {
return sqrt(a * 100);
}
};
System.out.println(formula.calculate(100)); // 100.0
System.out.println(formula.sqrt(16)); // 4.0
}
}
interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
函数式接口
Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以也可以给你的函数式接口添加默认方法。可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保接口一定达到这个要求,只需要给接口添加 @FunctionalInterface 注解,编译器如果发现标注了这个注解的接口有多于一个抽象方法的时候会报错的。
[java] view
plain copy
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
[java] view
plain copy
Converter<String, Integer> converter = (aa) -> Integer.valueOf(aa);
Integer converted = converter.convert("123");
System.out.println(converted); // 123
需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的。
JDK8中新增了一个包,java.util.function,这个包里有一些专门给新增的API使用的函数接口。
下面列出几个java.util.function中定义的接口:
[java] view
plain copy
public interface Consumer<T> : void accept(T t);//在T上执行一个操作,无返回结果
public interface Supplier<T> : T get();//无输入参数,返回T的实例
public interface Predicate<T> : boolean test(T t);// 输入参数为T的实例,返回boolean值
public interface Function<T, R> : R apply(T t);// 输入参数为T的实例,返回R的实例
方法引用:
静态方法引用: String::valueOf
非静态方法引用: Object::toString
继承的函数引用: x::toString
构造函数引用: ArrayList::new
方法引用 等价的lambda表达式
String::valueOf x -> String.valueOf(x)
Object::toString x -> x.toString()
x::toString () -> x.toString()
ArrayList::new () -> new ArrayList<>()
相关文章推荐
- struts2工作原理
- 【leetcode】【61】Rotate List
- Java8の字符串操作
- SpringMVC源码解析 - HandlerAdapter - HandlerMethodArgumentResolver
- 同时需要32位和64为的java开发环境解决办法
- Java-No.15 内存泄露和内存溢出问题定位
- java.time时间/日期API
- 如何分析java.lang.IllegalArgumentException: Cannot draw recycled bitmaps异常
- SPRING IN ACTION 第4版笔记-第二章Wiring Beans-005-<constructor-arg>和c-namespace
- Java HotSpot(TM) 64-Bit Server VM warning: Attempt to deallocate stack guard pages failed
- Spark:用Scala和Java实现WordCount
- Spring MVC那点事儿
- Java 包(package)
- Java 接口
- Java 封装
- Java 抽象类
- Java 多态
- Java继承关系的父子类中相同的成员变量
- 对Struts2的理解
- 深入解析Java并发程序中线程的同步与线程锁的使用