Java8 新特性之Lambda表达式
1. Lambda 表达式概述
- Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递);
- Lambda 表达式可以写出更简洁,更灵活的代码;
// Lambda 表达式入门程序
public class TestLambda{
List<Employee> employees = Arrays.asList(
new Employee("张三",16,1000),
new Employee("李四",22,2000),
new Employee("熊大",25,1300),
new Employee("熊二",32,1200),
new Employee("赵六",43,3200)
);
@Test
public void test2(){
List<Employee> list = filterEmpByAge(employees);
for(Employee emp : list){
System.out.println(emp);
}
}
// 需求一: 获取当前公司中,员工年龄大于等于30的员工信息
public List<Employee> filterEmpByAge(List<Employee> list){
List<Employee> emps = new ArrayList<>();
for(Employee emp : list){
if(emp.getAge() >= 30){
emps.add(emp);
}
}
return emps;
}
// 需求二: 获取当前公司中,员工工资大于等于2000的员工信息
public List<Employee> filterEmpBySal(List<Employee> list){
List<Employee> emps = new ArrayList<>();
for(Employee emp : list){
if(emp.getSalary() >= 2000){
emps.add(emp);
}
}
return emps;
}
// 优化方式一: 策略设计模式
@Test
public void test3(){
// 按年龄过滤
List<Employee> list = filterEmployee(employees,new FilterEmployeeByAge());
for(Employee employee : list){
System.out.println(employee);
}
// 按工资过滤
List<Employee> list2 = filterEmployee(employees,new FilterEmployeeBySal());
for(Employee employee : list2){
System.out.println(employee);
}
}
public List<Employee> filterEmployee(List<Employee> list, MyPredicte<Employee> mp){
List<Employee> emps = new ArrayList<>();
for(Employee employee : list){
if(mp.test(employee)){
emps.add(employee);
}
}
}
// 优化方式二: 匿名内部类
// 不再需要创建泛型接口的实现类
@Test
public void test4() {
// filterEmployee(employees, 匿名内部类);
List<Employee> list = filterEmployee(employees, new MyPredicate<Emplooyee>(){
public boolean test(Employee emp){
return emp.getSalary() <= 2000;
}
});
for(Employee employee : list){
System.out.println(employee);
}
}
// 优化方式三: Lambda 表达式
@Test
public void test5(){
List<Employee> list = filterEmployee(employees, (e) -> e.getSalary() <= 2000);
list.forEach(System.out::println);
}
// 优化方式四: Stream API
@Test
public void test6(){
employees.stream()
.filter((e) -> e.getSalary() <= 2000)
.forEach(System.out::println);
// 获取所有员工的名字
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
}
}
// 创建泛型接口
public interface MyPredicate<T>{
public boolean test(T t);
}
// 创建泛型接口的实现类
public class filterEmpByAge implements MyPredicate<Employee> {
public boolean test(Employee emp){
return emp.getAge() >= 30;
}
}
public class filterEmpBySal implements MyPredicate<Employee> {
public boolean test(Employee emp){
return emp.getSalary() >= 2000;
}
}
2. Lambda 表达式基础语法
->: 该操作符称为箭头操作符或Lambda 操作符,将Lambda 表达式拆分成两部分:- 左侧: Lambda 表达式的参数列表;
- 右侧: Lambda 表达式所需执行的功能,即 Lambda 体;
- 语法格式一: 无参数,无返回值
() -> System.out.println("Hello Lambda!");
- 语法格式二: 有一个参数,无返回值;
(x) -> System.out.println(x);- 或者
x -> System.out.println(x);若只有一个参数,小括号可以省略不写;
- 语法格式三: 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句;
- Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器可以通过上下文推断出数据类型,即"类型推断";
(Integer x, Integer y) -> Integer.compare(x,y);其中,数据类型 Integer,可以省略不写;
// 测试类
public class TestLambda{
@Test
public void test01(){
int num = 0; // JDK 1.7 之前,必须是final,才能在匿名函数内部使用
// JDK 1.8 可以不使用 final, 但是在匿名函数内部仍然不能进行运算
// 无参数,无返回值
// 1. Java8 之前写法:
Runnable r = new Runnable(){
public void run(){
System.out.println("Hello World!" + num);
}
};
r.run();
// Lambda 表达式
Runnable r2 = () -> System.out.println("Hello World!");
r2.run();
}
@Test
public void test02(){
// 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
Comparator<Integer> com = (x,y) -> {
System.out.println("函数式接口");
return Integer.compare(x,y);
};
// 有两个以上的参数,有返回值,Lambda 体中只有一条语句; 大括号和return可以省略
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
}
}
3. Lambda 表达式需要"函数式接口"的支持
- 函数式接口:接口中只有一个抽象方法时,称为函数式接口;
- 可以使用注解
@FunctionalInterface进行修饰,这样,可以检查该接口是否是函数式接口;
// Lambda 练习
// 声明一个带两个泛型的函数式接口,泛型类型为<T,R>, T 为参数, R 为返回值;
// 接口中声明对应抽象方法;
// 在 TestLambda 类中声明方法,使用接口作为参数,计算两个 long 型参数的和与乘积
// 函数式接口
@FunctionalInterface
public interface MyFunction<T,R>{
public R getValue(T t1, T t2);
}
// 测试类
public class TestLambda{
public void option(Long l1, Long l2, MyFunction<Long,Long> mf){
System.out.println(mf.getValue(l1,l2));
}
@Test
public void test(){
option(100L,200L,(x,y) -> x+y);
option(100L,200L, (x,y) -> x*y);
}
}
4. 四大内置核心函数式接口
- 消费型接口:
Consumer<T>- 参数类型: T
- 返回值类型: void
- 用途: 对类型为T的对象进行操作,包含方法:
void accept(T t)
- 供给型接口:
Supplier<T>- 参数类型: 无
- 返回值类型: T
- 用途: 返回类型为T的对象,包含方法:
T get()
- 函数型接口:
Function<T,R>- 参数类型: T
- 返回值类型: R
- 对类型为T的对象进行操作,并返回结果,结果是R类型的对象,包含方法:
R apply(T t)
- 断言型接口:
Predicate<T>- 参数类型: T
- 返回值类型: boolean
- 确定类型为T的对象是否满足某约束,并返回boolean值;包含方法:
boolean test(T t)
5. 方法引用
- 方法引用: 若 Lambda 体中的内容有方法已经实现了,我们可以使用"方法引用";
可以理解为,方法引用是 Lambda 表达式的另外一种表现形式; - 主要有三种语法格式:
对象::实例方法名类::静态方法名类::实例方法名- 注意: Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
- 注意2: 若 Lambda 参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用
ClassName::method方式调用;
5.1 构造方法引用
ClassName::new- 注意: 需要调用的构造器参数列表要与函数式接口中抽象方法的参数列表保持一致!
5.2 数组引用
Type::new
public class TestMethodRef{
@Test
public void test(){
Consumer<String> con = (x) -> System.out.println(x);
con.accept("测试方法....");
//对象::实例方法名
Consumer<String> con2 = System.out::println;
con2.accept("测试方法");
// 示例二: 获取员工姓名
Employee emp = new Employee();
Supplier<String> sup = () -> emp.getName();
String str = sup.get();
System.out.println(str);
Supplier<String> sup2 = emp::getName;
String str2 = sup2.get();
System.out.println(str2);
}
@Test
public void test2(){
// 类::静态方法名
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
Comparator<Integer> com2 = Integer::compare;
}
@Test
public void test3(){
// 类::实例方法名
BiPredicate<String,String> bp = (x,y) -> x.equals(y);
Bipredicate<String,String> bp2 = String::equals;
}
@Test
public void test4(){
Supplier<Employee> sup = () -> new Employee();
// 构造器引用(无参构造器)
Supplier<Employee> sup2 = Employee::new;
Function<Integer,Employee> fun = (x) -> new Employee(x);
// 构造器引用(有一个参数的构造器)
Function<Integer,Employee> fun = Employee::new;
}
@Test
public void test5(){
Function<Integer,String[]> fun = (x) -> new String[x];
String[] strs = fun.apply(10);
System.out.println(strs.length);
// 数组方式的引用
Function<Integer,String[]> fun2 = String[]::new;
}
}
参考资料
Java8 新特性之Lambda表达式的更多相关文章
- java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合
java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...
- Java8 新特性学习 Lambda表达式 和 Stream 用法案例
Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...
- Java8新特性之Lambda表达式
lambda表达式是java8给我们带来的几个重量级新特性之一,借用lambda表达式,可以让我们的java程序设计更加简洁.最近新的项目摒弃了1.6的版本,全面基于java8进行开发,本文是java ...
- 【Java8新特性】Lambda表达式基础语法,都在这儿了!!
写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...
- 【Java8新特性】- Lambda表达式
Java8新特性 - Lambda表达式 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...
- 夯实Java基础(二十二)——Java8新特性之Lambda表达式
1.前言 Java 8于14年发布到现在已经有5年时间了,经过时间的磨练,毫无疑问,Java 8是继Java 5(发布于2004年)之后的又一个非常最重要的版本.因为Java 8里面出现了非常多新的特 ...
- java8新特性之——lambda表达式的使用
lambda表达式简介 个人理解,lambda表达式就是一种新的语法,没有什么新奇的,简化了开发者的编码,其实底层还是一些常规的代码.Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解 ...
- 【Java8新特性】Lambda表达式
一.Lambda 表达式 是什么? Lambda读音:拉姆达. Lambda是一个匿名函数,匿名函数就是一个没有名字的函数. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). ...
- Java8 新特性(一)- Lambda 表达式
2014年3月18日发布了JavaSE 8 不追求技术的新,追求技术的稳定 本质:Lambda 表达式是一个匿名函数 作用:简化代码,增强代码的表达力 Lambda 语法格式 // 格式1:无参无返回 ...
随机推荐
- 0070 过滤器调用Spring的bean操作数据库
假设有这样的需求:将用户每次请求的ip.时间.请求.user-agent存入数据库,很明显可以用过滤器实现,在过滤器中获取到这些数据调用mybatis的mapper存入数据库,但问题来了:mybati ...
- cf339d Xenia and Bit Operations
Xenia and Bit Operations Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & ...
- 彻底解决_OBJC_CLASS_$_某文件名", referenced from:问题(转)
PS: 本文为转载而来,如有冲突,请与我联系,将立即删除. 最近在使用静态库时,总是出现这个问题.下面总结一下我得解决方法: 1. .m文件没有导入 在Build Phases里的Compile ...
- 一款基于css3的散子3D翻转特效
css3使我们能够跳出2d空间,实现3维空间的动画效果,这里给出一个自动翻转的3d色子动画效果制作过程. 第一步,首先进行HTML的布局,对于3D效果,布局有一定的规律,代码如下: <body& ...
- HttpURLConnection的使用
import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; ...
- DRBD 高可用配置详解(转)
高可用性集群解释:一般是指当集群中有某个节点失效的情况下,其上的任务会自动转移到其他正常的节点上.还指可以将集群中的某节点进行离线维护再上线,该过程并不影响整个集群的运行.今天来做个Heartbeat ...
- 常用的easyui使用方法
-------datagrid 1.获取某行的行号(row)tdg.datagrid('getRowIndex',rows)2.通过行号移除该行tdg.datagrid('deleteRow',ind ...
- 通过http输出流的方式从将html写入到Excel
private void HtmlResponseToExecl() { //将数据(html)导入到Excel中 Response.Charset = "gb2312"; Res ...
- VMware ESXi 启动时提示引导错误:不是VMware引导槽。找不到管理程序(bank6 not a vmware boot bank no hypervisor found)
VMware ESXi 启动时提示引导错误: bank6 not a vmware boot bank no hypervisor found 大概中文意思是:不是VMware引导槽.找不到管理程序. ...
- 【BZOJ】1609: [Usaco2008 Feb]Eating Together麻烦的聚餐(dp+被坑)
http://www.lydsy.com/JudgeOnline/problem.php?id=1609 首先我不得不说,我被这题坑了.题目前边没有说可以不需要3种牛都有啊!!!!!!!!然后我一直在 ...