jdk1.8新特性_Lambda表达式的引入
引入
需求: 获取工资大于20000的员工信息
public class Employee {
private String name;
private int age;
private Double salary;
public String address;
public Employee() {
}
public Employee(String name, int age, Double salary, String address) {
this.name = name;
this.age = age;
this.salary = salary;
this.address = address;
}
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
", address='" + address + '\'' +
'}';
}
}
--------------------------------------------------------------------
package com.gl;
import com.gl.domain.Employee;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class JDK8Test {
//获取工资大于20000的员工信息
List<Employee> emps = Arrays.asList(
new Employee("张三", 23, 14000.11, "深圳"),
new Employee("李四", 34, 26000.33, "北京"),
new Employee("王五", 55, 18000.00, "上海"),
new Employee("赵六", 32, 22000.88, "广州"),
new Employee("田七", 23, 14000.11, "深圳")
);
@Test
public List<Employee> getEmpInfo() {
List<Employee> employees = new ArrayList<>();
for (Employee emp : emps) {
if (emp.getSalary() > 20000) {
employees.add(emp);
}
}
return employees;
}
**//思考: 如果是提取年龄大于30 或者地址在深圳的,还是一通for循环,代码的可读性不高->抽取方法
//新增一个接口MyPredicate FilterEmployee 再实现此接口**
public interface MyPredicate<T> {
public boolean test(T t);
}
public class FilterEmployee implements MyPredicate<Employee>{
@Override
public boolean test(Employee employee) {
return employee.getAge()>30;
}
}
//优化方式1 策略设计模式(缺点:每次都得创建类 实现接口FilterEmployee,太麻烦了)
@Test
public void test2() {
List<Employee> employees = filterEmp(emps, new FilterEmployee());
System.out.println("employees = " + employees);
//李四 王五 赵六
}
public List<Employee> filterEmp(List<Employee> list, MyPredicate<Employee> mp) {
ArrayList<Employee> ems = new ArrayList<>();
for (Employee employee : list) {
if (mp.test(employee)) {
ems.add(employee);
}
}
return ems;
}
//优化方式2:使用匿名内部类的方式处理(缺点:代码可读性差,不够简洁)
@Test
public void test3(){
List<Employee> employees = filterEmp(emps, new MyPredicate<Employee>() {
@Override
public boolean test(Employee employee) {
return employee.getAge()>30;
}
});
for (Employee employee : employees) {
System.out.println("employee = " + employee);
}
//李四 王五 赵六
}
//优化方式3: 使用Lambda表达式
@Test
public void test4(){
List<Employee> employees = filterEmp(emps, (employee) -> employee.getAge() > 30);
employees.forEach(System.out::println);
//李四 王五 赵六
}
//优化方式4 没有接口和实现类: 使用Lambda表达式 stream API
@Test
public void test5(){
emps.stream().filter(employee -> employee.getAge() > 30).forEach(System.out::println);
//李四 王五 赵六
}
-----------------------------------------------------------------------
**一. Lambda 表达式的基础语法:Java8中引用了一个新的操作符"->"该操作称为箭头操作符或
-
Lambda 操作符,箭头操作符将Lambda 表达式分为两部分:
- 左侧: Lambda表达式的参数列表
- 右侧: Lambda 表达式中所需执行的功能,即 Lambda 体**
public class testLambda2 {
//语法格式1: 无参数 无返回值
@Test
public void test1() {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Hello KuGou!");
}
};
r.run();
//只打印 Hello KuGou!
}
/语法格式2:有一个参数 并且无返回值
@Test
public void test2(){
Consumer<String> con = (x) -> System.out.println(x);
con.accept("中国队 加油!");
//语法3:若只有一个参数,小括号可以省略不写
@Test
public void test3(){
Consumer<String> con = x -> System.out.println(x);
con.accept("中国队 加油加油!");
}
//语法格式4:有两个以上的参数,有返回值,并且Lambda 体中有多条语句
@Test
public void test4() {
Comparator<Integer> com = (x, y) -> {
System.out.println("函数式接口");
return Integer.compare(x, y);
};
}
//语法5:若 Lambda 体中只有一条语句, return 和大括号都可以省略
@Test
public void test5() {
Comparator<Integer> comparator = (Integer x, Integer y) -> Integer.compare(x, y);
}
//语法6: Lambda 表达式的类型参数列表的数据类型可以省略不写,因为JVM编译器可以通过上下文推断出数据类型,即"类型推断"
@Test
public void test6() {
Comparator<Integer> comparator = ( x, y) -> Integer.compare(x, y);
}
**/*
* 总结:
* 上联:左右遇一括号省
* 下联:左侧推断类型省
* 横批:能省则省
*
* */**
}
二. Lambda 表达式需要"函数式接口"的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口.可以使用 @FunctionlInterface 注解修饰可以检测是否是函数式接口
//练习1
@Test
public void test11() {
Collections.sort(emps, (e1, e2) -> {
if (e1.getAge() == e2.getAge()) {
return e1.getName().compareTo(e2.getName());
} else {
return -Integer.compare(e1.getAge(), e2.getAge());
}
});
for (Employee emp : emps) {
System.out.println("emp = " + emp);
}
}
//练习2
@Test
public void test22() {
String s = StringHandeler(" 我的大中国呀 ", str -> str.trim());
System.out.println("s = " + s);//s = 大中国
String s2 = StringHandeler("good", str -> str.toUpperCase());
System.out.println("s2 = " + s2); //s2 = GOOD
String s3 = StringHandeler("我的大中国呀", str -> str.substring(2,5));
System.out.println("s3 = " + s3); //s3 = 大中国
}
//处理字符串的方法
public String StringHandeler(String str, MyFunction f) {
return f.getStr(str);
}
//练习3 定义函数式接口
public interface MyFunction2<T,R> {
public R getValue(T t1, T t2);
}
@Test
public void test33(){
op(100L,200L,(x,y)->x+y); //300
op(100L,200L,(x,y)->x*y); //20000
}
//需求: 对两个Long 型数据进行处理
public void op(Long l1,Long l2, MyFunction2<Long,Long> mf){
System.out.println(mf.getValue(l1,l2));
}