一个 lambda 表达式具有下面这样的语法特征。它由三个部分组成:第一部分为一个括号内用逗号分隔的参数列表,参数即函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块。语法如下:
parameter -> expression body
函数接口是一种只有一个方法的接口,可以隐式地转换成 Lambda 表达式。函数接口的存在使得方法代码作为数据被对待。
package com.tracy.algorithmeditionfour.chapter1;
public class Operator {
interface MathOperation{
int operation(int a,int b);
}
private int operate(int a,int b,MathOperation mathOperation){
return mathOperation.operation(a,b);
}
public static void main(String[] args) {
Operator operator = new Operator();
/**
* 下面展示函数式接口和lambda表达式的语法:
* 四个句子分别实现加、减、乘、除功能,语法不同但效果是类似的。
*/
MathOperation add = (a, b) -> a + b;//不指定参数类型,不使用return关键词
MathOperation sub = (int a, int b) -> a - b;//指定参数类型
MathOperation multi = (a, b) -> {//使用return关键词,同时也必须使用大括号
return a * b;
};
MathOperation div = (a, b) -> a / b;
/**
* 调用函数式接口
*/
System.out.println("2+3="+operator.operate(2,3,add));
System.out.println("2-3="+operator.operate(2,3,sub));
System.out.println("2*3="+operator.operate(2,3,multi));
System.out.println("2/3="+operator.operate(2,3,div));
}
}
运行结果:
2+3=5
2-3=-1
2*3=6
2/3=0
方法引用可以通过方法的名字来引用其本身。它可以用来引用下列类型的方法:
(1)构造器引用。语法是 Class::new,或者更一般的 Class< T >::new,要求构造器方法是没有参数。
(2)静态方法引用。语法是 Class::static_method,要求接受一个 Class 类型的参数。
(3)特定类的任意对象方法引用。它的语法是 Class::method,要求方法是没有参数的。
(4)特定对象的方法引用,它的语法是 instance::method。要求方法接受一个参数,与 3 不同的地方在于,3 是在列表元素上分别调用方法,而 4 是在某个对象上调用方法,将列表元素作为参数传入。
List<String> names = new ArrayList<>();
names.add("Peter");
names.add("Linda");
names.add("Smith");
names.add("Zack");
names.add("Bob");
// 通过 System.out::println 引用了输出的方法
names.forEach(System.out::println);
运行结果:
Peter
Linda
Smith
Zack
Bob
在java.util.Funtion包中,有许多和函数式编程相关的API,这里我就不列举了。
下面展示下函数式编程:
package com.tracy.algorithmeditionfour.chapter1;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class FunctionDev {
public static void eval(List<Integer> list, Predicate<Integer> predicate){
for(Integer i:list){
if(predicate.test(i)){
System.out.println(i);
}
}
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println("全部数字:");
//等同于list.forEach(n -> System.out.println(n));
eval(list,n->true);
System.out.println("偶数:");
//等同于list.forEach(n ->{if(n%2==0) System.out.println(n);});
eval(list,n->n%2==0);
System.out.println("奇数:");
//等同于list.forEach(n ->{if(n%2==1) System.out.println(n);});
eval(list,n->n%2==1);
}
}
运行结果:
全部数字:
1
2
3
4
5
6
7
8
9
10
偶数:
2
4
6
8
10
奇数:
1
3
5
7
9
Java 8 引入默认方式使得 List 和 Collection 接口能够拥有 forEach 方法的默认实现。实现了这些接口的类也不必再实现相同的功能了。
public interface Girl{
default void print(){
System.out.println("I am a goy.");
}
}
public class NewFeaturesTester{
public static void main(String args[]){
Younger younger = new Student();
younger.print();
}
}
interface Younger{
default void print(){
System.out.println("I am a younger.");
}
static void sayHi(){
System.out.println("Young is the capital.");
}
}
interface Learner{
default void print(){
System.out.println("I am a learner.");
}
}
class Student implements Younger, Learner{
public void print(){
Younger.super.print();
Learner.super.print();
Younger.sayHi();
System.out.println("I am a student!");
}
}
运行结果:
I am a younger.
I am a learner.
Young is the capital.
I am a student!
在 Java 官方文档的解释中,它是一个可以为 null 的容器对象。如果值存在则 isPresent() 方法会返回 true,调用 get()方法会返回该对象。使用这个类会提高代码的鲁棒性。
package com.tracy.algorithmeditionfour.chapter1;
import java.util.Optional;
public class Option_test {
public Integer sum(Optional<Integer> a,Optional<Integer> b){
System.out.println("a存在:"+a.isPresent());
System.out.println("b存在:"+b.isPresent());
Integer value_a=a.orElse(new Integer(0));//如果a为null则返回0,否则返回a
Integer value_b=b.get();//使用这个方法的前提是b必须有正常值
return value_a+value_b;
}
public static void main(String[] args) {
Option_test option=new Option_test();
Integer a=null;
Integer b=new Integer(3);
Optional<Integer> a_o=Optional.ofNullable(a);//允许传入null值
Optional<Integer> b_o=Optional.ofNullable(b);//不允许传入null值
System.out.println(option.sum(a_o,b_o));
}
}
运行结果:
a存在:false
b存在:true
3
Java 8 引入了 Stream(流式操作),我们可以通过该操作实现对集合的并行处理和函数式操作。Collection 是一种静态的内存数据结构,而 Stream 是面向计算的。
API的学习看这位大哥的博客:这里跳转