Lanmbda的表达式简介
- lambda表达式是一个匿名函数,我们可以将Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到提升。
案例
- 下面两个案例让你感受Lambda表达式 及 java8的魅力
- 案例 1
import java.util.Comparator;
import java.util.TreeSet;
import org.junit.Test;
public class TestLambda {
//原来的匿名内部类
@Test
public void test1() {
Comparator<Integer> com = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
TreeSet<Integer> ts = new TreeSet<>(com);
}
//Lambda表达式
public void test2() {
Comparator<Integer> com = (x,y) ->Integer.compare(x,y);
TreeSet<Integer> ts = new TreeSet<>(com);
}
}
- 案例2
//实体类 的 构造
public class Employee {
private String name;
private int age;
private double salary;
public Employee() {
}
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
}
- 需求1:获取当前公司中员工年龄大于35的员工信息
- 需求2:获取当前公司中员工工资大于5000的员工信息
一. 解决方案一:最基本的java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class Test11 {
static List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",38,5555.99),
new Employee("王五",18,6666.66),
new Employee("赵六",18,3333.33),
new Employee("田七",18,7777.77)
);
@Test
public void test1() {
List<Employee> list = filterEmpLoyees(employees);
System.out.println(list.toString());
}
@Test
public void test2() {
List<Employee> list2 = filterEmployees2(employees);
System.out.println(list2.toString());
}
//需求1:获取当前公司中员工的年龄大于35的员工信息
public List<Employee> filterEmpLoyees(List<Employee> employees){
List<Employee> list = new ArrayList<>();
for (Employee employee : employees) {
if(employee.getAge()>35) {
list.add(employee);
}
}
return list;
}
//需求2:获取当前公司中员工的工资大于
public List<Employee> filterEmployees2(List<Employee> employees){
List<Employee> list = new ArrayList<>();
for (Employee employee : employees) {
if(employee.getSalary() >= 5000) {
list.add(employee);
}
}
return list;
}
}
解决方案二.定义接口:策略设计模式
- 接口与接口的实现
//首先定义一个过滤的接口
public interface MyPredicate<T> {
public boolean test(T t);
}
//用这个接口 实现过滤 年龄的实现类
public class FilterEmployeeByAge implements MyPredicate<Employee>{
@Override
public boolean test(Employee t) {
return t.getAge()>35;
}
}
//用这个接口 实现过滤 工资的实现类
public class FilterEmployeeBySalary implements MyPredicate<Employee>{
@Override
public boolean test(Employee t) {
return t.getSalary()>=5000;
}
}
//需求1的实现
@Test
public void test4() {
List<Employee> list = filterEmployee(employees, new FilterEmployeeByAge());
for (Employee employee : list) {
System.out.println(employee);
}
}
//需求2的实现
@Test
public void test5() {
List<Employee> list = filterEmployee(employees, new FilterEmployeeBySaraly());
for (Employee employee : list) {
System.out.println(employee);
}
}
//通过接口来实现过滤
public List<Employee> filterEmployee(List<Employee> employees,MyPredicate<Employee> mp){
List<Employee> list = new ArrayList<>();
for (Employee employee : employees) {
if(mp.test(employee)) {
list.add(employee);
}
}
return list;
}
- 匿名内部类
//优化方式:匿名内部类
@Test
public void test5() {
List<Employee> filterEmployee = filterEmployee(employees, new MyPredicate<Employee>() {
@Override
public boolean test(Employee t) {
return t.getSalary() <= 5000;
}
});
filterEmployee.forEach(System.out::println);
}
- Lambda表达式
//Lambda表达式
@Test
public void test6() {
List<Employee> filterEmployee = filterEmployee(employees, e->e.getSalary()<= 5000);
filterEmployee.forEach(System.out::println);
}
- stream API
//StreamAPI
@Test
public void test7() {
employees.stream()
.filter(e-> e.getSalary() <= 5000)
.forEach(System.out::println);
}
lambda 表达式基础语法
Lambda表达式基础语法的学习
/*
* 一、Lambda表达式的基础语法:Java 8 中引入了一个新的操作符 "->" 该操作符成为箭头操作符或 Lambda 操作符
* 箭头操作符将Lambda表达式 分成两个部分
*
* 左侧:Lambda 表达式的参数列表
* 右侧:Lambda 表达式中所需要执行的功能,即Lambda 体
*
* 二、语法格式
* 语法格式一、无参数,无返回值
* () ->System.out.println("hello world !" +num);
* 语法格式二、有一个参数,并且无返回值
* (s)->System.out.println(s)
* 语法格式三、若只有一个参数,小括号可以省略不写
* x->System.out.println(x)
* 语法格式四、有两个以上的参数,有返回值,并且Lambda 体中有多条语句
* Comparator<Integer> com = (x,y) ->{
* return Integer.compare(x, y);
* };
* 语法格式五、若Lambda体中只有一个语句,return 与 大括号 都可以不写
* (x,y) ->Integer.compare(x, y);
* 语法格式六、Lambda 表达式 的参数列表 的数据类型 可以省略不写 ,因为JVM 编译器通过上下文 推断出,数据类型,即"类型推断"
* (Integerx,Integery) ->Integer.compare(x, y);
*
*/
/**
* 语法格式一、无参数,无返回值
* () ->System.out.println("hello world !" +num);
*/
@Test
public void test1() {
int num = 0; // final 的 变量 ,jdk 1.7之前需要添加final 修饰词,1.8 后可以省略不写
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("hello world !!"+ num);
}
};
r.run();
System.out.println("------------");
Runnable r1 = () ->System.out.println("hello world !" +num);
r1.run();
}
/**
*
* 语法格式二、有一个参数,并且无返回值
* (s)->System.out.println(s)
* 语法格式三、若只有一个参数,小括号可以省略不写
* x->System.out.println(x)
*
*/
@Test
public void test2() {
Consumer<String> con = (s)->System.out.println(s);
con.accept("大家好!!");
System.out.println("------");
Consumer<String> con1 = s->System.out.println(s);
con1.accept("大家好!!");
}
/**
*语法格式四、有两个以上的参数,有返回值,并且Lambda 体中有多条语句
* Comparator<Integer> com = (x,y) ->{
* return Integer.compare(x, y);
* };
* 语法格式五、若Lambda体中只有一个语句,return 与 大括号 都可以不写
* (x,y) ->Integer.compare(x, y);
*/
@Test
public void test3() {
Comparator<Integer> com = (x,y) ->{
return Integer.compare(x, y);
};
System.out.println("----------");
Comparator<Integer> com1 = (x,y) ->Integer.compare(x, y);
}
/**
* 语法格式六、Lambda 表达式 的参数列表 的数据类型 可以省略不写 ,因为JVM 编译器通过上下文 推断出,数据类型,即"类型推断"
* (Integer x,Integer y) ->Integer.compare(x, y);
*/
@Test
public void test5() {
// (Integer x, Integer y) 这里的 Integer 可以不写
Comparator<Integer> com = (Integer x, Integer y) ->Integer.compare(x, y);
//类型推断1.8 升级了 HashMap<>这里的也不用写
show( new HashMap<>());
}
public void show(Map<String,Integer> map) {
}
函数式接口
/*
* 二、Lambda 表达式 需要 "函数式" 的支持
*
* 函数式接口:接口中只有一个抽象的方法的接口,称为函数式接口。可以使用注解 @FunctionalInterface
*
*/
@FunctionalInterface
public interface MyPredicate<T> {
public boolean test(T t);
//@FunctionalInterface 有这个注解 再定义别的接口 会报错
//public boolean test2(T t);
}
自定义一个函数式接口,并使用
@FunctionalInterface
public interface MyFun {
public Integer getValue(Integer num);
}
//需求:对一个数,进行运算
@Test
public void test6() {
Integer num = operation(100, x->x*x);
System.out.println(num);
Integer num2 = operation(200, y->y+200);
System.out.println(num2);
}
public Integer operation(Integer num , MyFun mf) {
return mf.getValue(num);
}
练习
题目
-
调用Colleactions.sort()方法,通过定制排序比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda 作为参数传递。
-
①声明函数式接口,接口中声明抽象方法,public String getValue(String str);
功能1、将一个字符串转换成大写,并返回
功能2、将一个字符串转换成从第二个到第四个进行截取形成一个新的字符串,并返回 -
声明一个带两个泛型的函数式接口。泛型类型为<T,R> T为参数,R为返回值。
接口中声明对应的抽象方法
功能1、计算两个long类型参数的和
功能2、计算两个long类型参数的乘积
答案
第一题:
static List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",38,5555.99),
new Employee("王五",18,6666.66),
new Employee("赵六",18,3333.33),
new Employee("田七",18,7777.77)
);
// 1. 调用Colleactions.sort()方法,通过定制排序比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda 作为参数传递。
@Test
public void test3() {
Collections.sort(employees, (e1,e2)->{
if(e1.getAge() == e2.getAge()) {
return e1.getName().compareTo(e2.getName());
}else {
return Integer.compare(e1.getAge(), e2.getAge());
}
});
}
第二题:
//定义一个接口
@FunctionalInterface
public interface Myfunction {
public String getValue(String str);
}
//功能实现
@Test
public void test44() {
String strHandler1 = strHandler("abcdefg", str->str.toUpperCase());
String strHandler2 = strHandler("abcdefg",str->str.substring(1, 3));
}
public String strHandler(String str , Myfunction mf) {
return mf.getValue(str);
}
第三题:
//定义接口
@FunctionalInterface
public interface Myfunction2<T,R> {
public R getValue(T t1,T t2);
}
//功能实现
@Test
public void test9() {
op(1L,2L, (x,y) -> x+y);
op(3L,4L , (x,y) -> x*y);
}
public void op(Long l1, Long l2,Myfunction2<Long, Long> mf) {
System.out.println(mf.getValue(l1, l2));
}