Lambda表达式和函数式编程html
http://www.javashuo.com/article/p-kcswmwel-bt.htmljava
https://www.runoob.com/java/java8-lambda-expressions.htmlgit
函数接口是指内部只有一个接口函数的接口。express
在Lambda表达式以前,新建一个线程这样写:编程
new Thread(new Runnable(){
@Override
public void run(){
System.out.println("Thread run()");
}
}).start();ide
有Lambda表达式以后,则能够这样写:
new Thread( () -> System.out.println("Thread run()") ).start();函数式编程
如上所示,Lambda表达式一个常见用法是取代(某些)匿名内部类,但Lambda表达式的做用不限于此。函数
Runnable run = () -> System.out.println("Hello World");// 1
ActionListener listener = event -> System.out.println("button clicked");// 2
Runnable multiLine = () -> {// 3
System.out.println("Hello ");
System.out.println("World");
};
BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4
BinaryOperator<Long> addImplicit = (x, y) -> x + y;// 5优化
Lambda表达式的另外一个重要用法,是和Stream一块儿使用。
Stream is a sequence of elements supporting sequential and parallel aggregate operations。
Stream就是一组元素的序列,支持对这些元素进行各类操做,这些操做经过Lambda表达式指定。
能够把Stream看做Java Collection的一种视图,
就像迭代器是容器的一种视图那样(但Stream不会修改容器中的内容)。线程
下面例子展现了Stream的常见用法。
例子1
假设须要从一个字符串列表中选出以数字开头的字符串并输出,Java 7以前须要这样写:
List<String> list = Arrays.asList("1one", "two", "three", "4four");
for(String str : list){
if(Character.isDigit(str.charAt(0))){
System.out.println(str);
}
}
而Java 8就能够这样写:
List<String> list = Arrays.asList("1one", "two", "three", "4four");
list.stream()// 1.获得容器的Steam
.filter(str -> Character.isDigit(str.charAt(0)))// 2.选出以数字开头的字符串
.forEach(str -> System.out.println(str));// 3.输出字符串
上述代码首先1. 调用List.stream()方法获得容器的Stream,2. 而后调用filter()方法过滤出以数字开头的字符串,3. 最后调用forEach()方法输出结果。
使用Stream有两个明显的好处:
减小了模板代码,只用Lambda表达式指明所需操做,代码语义更加明确、便于阅读。
将外部迭代改为了Stream的内部迭代,方便了JVM自己对迭代过程作优化(好比能够并行迭代)。
例子2
假设须要从一个字符串列表中,选出全部不以数字开头的字符串,将其转换成大写形式,并把结果放到新的集合当中。Java 8书写的代码以下:
List<String> list = Arrays.asList("1one", "two", "three", "4four");
Set<String> newList =
list.stream()// 1.获得容器的Stream
.filter(str -> !Character.isDigit(str.charAt(0)))// 2.选出不以数字开头的字符串
.map(String::toUpperCase)// 3.转换成大写形式
.collect(Collectors.toSet());// 4.生成结果集
上述代码
1.调用List.stream()方法获得容器的Stream
2.调用filter()方法选出不以数字开头的字符串
3.调用map()方法将字符串转换成大写形式
4.调用collect()方法将结果转换成Set。
这个例子还向咱们展现了方法引用(代码标号3处)以及收集器(代码标号4处)的用法
经过这个例子咱们看到了Stream链式操做,即多个操做能够连成一串。不用担忧这会致使对容器的屡次迭代,由于不是每一个Stream的操做都会当即执行。Stream的操做分红两类,一类是中间操做(intermediate operations),另外一类是结束操做(terminal operation),只有结束操做才会致使真正的代码执行,中间操做只会作一些标记,表示须要对Stream进行某种操做。这意味着能够在Stream上经过关联多种操做,但最终只须要一次迭代。若是你熟悉Spark RDD,对此应该并不陌生。