lambda表达式的学习
Lambda表达式
为什么使用lambda表达式
Lambda表达式可以简化我们的代码,使我们只需要关注主要的代码就可以。
//测试用的实体类 public class Employee { private String name; private Integer age; private double salary; public Employee() { } public Employee(String name, Integer age, double salary) { this.name = name; this.age = age; this.salary = salary; } }
//定义要操作的集合数据 List<Employee> employees = Arrays.asList( new Employee("张三",18,3000), new Employee("李四",18,3000), new Employee("张三",45,8700), new Employee("王五",26,4500), new Employee("麻子",30,2700), new Employee("田七",15,200) );
//需求找出年龄大于20的员工 ---------------最常规的操作-------- //过滤方法 public List<Employee> filterEmployee(List<Employee> employees){ ArrayList<Employee> list = new ArrayList<>(); for (Employee employee : employees) { if(employee.getAge() > 20){ list.add(employee); } } return list; } //测试方法 @Test public void test1(){ List<Employee> employees = filterEmployee(this.employees); for (Employee employee : employees) { System.out.println(employee); } } //Employee{name='张三', age=45, salary=8700.0} //Employee{name='王五', age=26, salary=4500.0} //Employee{name='麻子', age=30, salary=2700.0} -------------第二种写法----------(策略模式) 1、先定义一个接口 public interface MyPredicate<T> { public boolean test(T t); } 2、定义过滤类实现我们定义的接口 public class FilterEmployeeByAge implements MyPredicate<Employee>{ @Override public boolean test(Employee employee) { return employee.getAge()>20; } } 3、同样定义过滤方法 //过滤方法 public List<Employee> filterEmployee(List<Employee> employees, Mypredicatre<Employee> mp){ ArrayList<Employee> list = new ArrayList<>(); for (Employee employee : employees) { if(mp.test){ list.add(employee); } } return list; } 4、测试方法 @Test public void test2(){ List<Employee> employees = filterEmployee(this.employees, new FilterEmployeeByAge()); for (Employee employee : employees) { System.out.println(employee); } } //Employee{name='张三', age=45, salary=8700.0} //Employee{name='王五', age=26, salary=4500.0} //Employee{name='麻子', age=30, salary=2700.0} -----------上面的方法每过滤不同的条件都要实现一个接口,不是很友好---------我们可以使用匿名内部类 @Test public void test3(){ List<Employee> employees = filterEmployee(this.employees, new MyPredicate<Employee>() { @Override public boolean test(Employee employee) { return employee.getAge() > 20; } }); -----------------匿名内部类可以使用lambda表达式简化---------- @Test public void test4(){ List<Employee> employees = filterEmployee(this.employees, (e) -> e.getAge() > 20); for (Employee employee : employees) { System.out.println(employee); } }
lambda表达式需要函数式接口支持。
函数式接口:只有一个方法的接口,可以用注解@FunctionalInterface修饰接口
语法格式:
- 无参数,无返回值 ()->System.out.println("hello word")
@Test public void test(){ Runnable r = new Runnable() { @Override public void run() { System.out.println("hello world"); } }; //------------------lambda----------------------------- Runnable r1 = ()-> System.out.println("hello world"); }
- 有一个参数,无返回值 (x)-> System.out.println(x) (有一个参数小括号可以不写)
@Test public void test2(){ Consumer<String> con = (x)-> System.out.println(x); //Consumer<String> con = x-> System.out.println(x); con.accept("hello world"); }
- 有两个参数,且有返回值 (有多条语句,必须使用{})
@Test public void test3(){ Comparator<Integer> com = (x,y)->{ System.out.println("函数式接口"); return Integer.compare(x,y); }; }
- 有两个参数,且有返回值,语句只有一条 (return 和{} 可以省略)
@Test public void test4(){ Comparator<Integer> com = (x,y)->Integer.compare(x,y); }
- lambda参数列表的数据类型可以省略不用写(类型推断)(要写都得写,不能写一个,一个不写)
java8中4大核心接口
Consumer
void accept(T t);
@Test public void test4(){ happy(1000,(m) -> System.out.println("你消费了:"+m+"元")); } public void happy(double money, Consumer<Double> con){ con.accept(money); }
Supplier
T get();
@Test //获取随机数 public void test5() { List<Integer> numList = getNumList(5, () -> (int) (Math.random() * 10)); System.out.println(numList.toString()); } //产生整数集合 public List<Integer> getNumList(int num, Supplier<Integer> sup) { ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < num; i++) { list.add(sup.get()); } return list; }
Function<T,R>: 函数式接口
R apply(T t);
@Test public void test6(){ String str = strHandle("hello world", (s) -> s.substring(2, 5)); System.out.println(str); } //对字符串进行处理返回一个字符串 public String strHandle(String str, Function<String,String> fun){ return fun.apply(str); }
Predicate
boolean test(T t);
@Test public void test7(){ List<String> strings = Arrays.asList("hello", "world", "qw", "das", "s", "sadui"); List<String> str = filterStr(strings, (s) -> s.length() > 3); System.out.println(str.toString()); } //对字符串数组进行过滤 public List<String> filterStr(List<String> str, Predicate<String> pre){ ArrayList<String> list = new ArrayList<>(); for (String s : str) { if(pre.test(s)){ list.add(s); } } return list; }
方法引用: 如果lambda体中的内容方法已经实现我们可以使用方法引用。
lambda表达式的另一种表现形式,
主要有三种语法格式:
Lambda体中方法的返回值要与实例方法返回值类型一致
- 对象::实例方法名
@Test public void test8(){ Consumer<String> con = (s) -> System.out.println(s); Consumer<String> con1 = System.out::println; PrintStream ps = System.out; Consumer<String> con2 = ps::println; Employee emp = new Employee(); Supplier<Integer> sup = () -> emp.getAge(); Integer age = sup.get(); Supplier<Integer> sup1 = emp::getAge(); Integer age1 = sup1.get(); }
- 类::静态方法名
@Test public void test9(){ Comparator<Integer> com = (x,y)-> Integer.compare(x,y); Comparator<Integer> com1 = Integer::compare; }
-
类::实例方法名
第一个参数是实例方法的调用者,第二参数是实例方法的参数才可以使用
@Test public void test10(){ BiPredicate<String,String> pre = (x,y)-> x.equals(y); BiPredicate<String,String> pre1 = String::equals; }
构造器引用:
className::new
需要调用的构造器函数列表要与函数式接口中的抽象方法的参数列表保持一致
@Test public void test1(){ Supplier<Employee> sup = () -> new Employee(); //调用的是无参构造器 Supplier<Employee> sup1 = Employee::new; //调用的是带有一个参数的构造器 Function<Integer,Employee> fun = Employee::new; }
数组引用:
Type[]::new
@Test public void test1(){ Function<Integer,String[]> fun = (x)-> new String[x]; Function<Integer,String[]> fun1 = String[]::new; }
成功没有捷径,一步一个脚印!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具