Java Lambda 表达式
Java Lambda表达式
Lambda 表达式被使用作提供一个功能接口的具体实现。节约代码。
在表达式中,不需要再定义方法提供实现,只需要编写具体实现的方法。
Lambda表达式会被视为一个函数,因此编译器不会创建.class
文件
方法接口
在Lambda表达式中,提供了方法接口的实现方式。如果一个接口只有一个抽象方法就可以称作是方法接口。
Java中提供了一个注解
@FunctionalInterface
,可以用它声明方法接口。
语法
(argument-list) -> {body}
一个表达式主要包含三部分:
Argument-list
:变量清单(可以为空)Arrow-token
:箭头body
:包含lambda表达式和语句
常用方式
(p1) -> {
//只有一个参数,不需要指定类型,可以不用括号
}
() -> {
System.out.println("Hello World");
}
(p1,p2) -> { return p1 + p2; }
(p1,p2) -> p1+p2;
//上面两种情况相同,只有一句返回值时,不需要return和大括号
//如果表达式正文只有一条语句,则必须包含在大括号中,返回类型也要和匿名返回类型相同
() -> { return 3.1415 };
方法引用
双冒号::
操作符是Java中的方法引用。当使用方法引用时,目标引用方法::
之前,目标引用提供的方法名放在::
之后,即目标引用::方法
Person::getAge;
Function
对象进行操作
// 获取 getAge 方法的 Function 对象
Function<Person, Integer> getAge = Person::getAge;
// 传参数调用 getAge 方法
Integer age = getAge.apply(p);
目标引用的参数类型是 Function<T,R>
,T
表示传入类型,R
表示返回类型。
比如,表达式 person -> person.getAge();
,传入参数是 person
,返回值是 person.getAge()
,那么方法引用 Person::getAge
就对应着 Function<Person,Integer>
类型。
使用示例
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
// 类型声明,参数类型的声明需要保持一致,即全部同时声明或不声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
// 没有大括号及返回语句。只有一句的时候,可以不包含return关键字
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
//循环
List<String> list1 = Arrays.asList("hello","good");
list1.forEach(
(n) -> System.out.println(n)
);
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}
注意
变量作用域
- 如果一个参数声明了类型,则所有的参数都需要声明变量类型
- 在Lambda表达式的变量中,不能和函数中声明的临时变量重复
Lambda表达式和匿名类的区别
两者的主要区别在于关键词的使用。对于匿名类,关键词this解释为匿名类,但是对Lambda表达式,关键词this会被写作时Lambda的外部类。
而造成这样的区别的主要原因就是两者的编译方法不同。Java编译器会编译Lambda表达式并将其转化为类中的私有函数,使用 Java 7 中新加的 invokedynamic
指令动态绑定该方法。参考
常用场景
1.创建线程对象
public class ThreadTest{
public static void main(){
Runnable r1 = () -> {
System.out.println("Thread1 is running ...");
};
Thread t1 = new Thread(r1);
t1.start();
Runnable r2 = () -> {
System.out.println("Thread2 is running ...");
};
Thread t2 = new Thread(r2);
t2.start();
}
}
2.集合框架的使用
Lambda表达式可以在集合框架中使用。可以提供高效简洁的方式实现迭代、过滤、获取数据。
使用场景
- 比较器 Comparator
- 过滤器 Filter
- 事件监听器 Event Listener
public class collectionFrameWorkLambda {
public static void main(String[] args) {
List<Product> list = new ArrayList<>();
//Adding Products
list.add(new Product(1,"HP Laptop",25000f));
list.add(new Product(3,"Keyboard",300f));
list.add(new Product(2,"Dell Mouse",150f));
//implementing lambda expression
//Comparator 比较器
Collections.sort(list,
(p1,p2)->(p1.name.compareTo(p2.name))
);
for (Product product : list) {
System.out.println(product.id+" "+ product.name+" "+ product.price);
}
//Filter Collection Data 过滤器
Stream<Product> productStream = list.stream().filter(product -> (product.price > 20000f));
productStream.forEach(
product -> System.out.println(product.name+":"+product.price)
);
//Event Listener 事件监听
JTextField tf = new JTextField();
tf.setBounds(50, 50, 150, 20);
JButton button = new JButton("click");
button.setBounds(80, 100, 70, 30);
// lambda expression implementing here.
button.addActionListener(e -> tf.setText("hello swing"));
JFrame f = new JFrame();
f.add(tf);
f.add(button);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(null);
f.setSize(300, 200);
f.setVisible(true);
}
}
class Product {
int id;
String name;
float price;
public Product(int id, String name, float price) {
this.id = id;
this.name = name;
this.price = price;
}
}
参考: