目录
码云地址:https://gitee.com/bufanli/java8-demo.git
lambda表达式概述
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
package cn.bufanli.lambda;
import cn.bufanli.pojo.Employee;
import cn.bufanli.service.MyEmployeesService;
import cn.bufanli.service.impl.MyEmployeesAgeServiceImpl;
import cn.bufanli.service.impl.MyEmployeesSalaryServiceImpl;
import org.junit.Test;
import java.beans.Visibility;
import java.util.*;
import java.util.function.Consumer;
/**
* 一.lambda表达式需要函数式接口的支持
* 函数式接口: 接口中只有一个方法的接口为函数式接口
* 使用 @FunctionalInterface 注解可以检查接口是否是函数是借口 和@Service 注解使用一样
* 二.lambda表达式的基础语法
* java8引入了一个新的操作符号 "->" 该操作符是箭头操作符或者lambda操作符
* 箭头操作符将lambda表达式拆分成左右两部分
* 左: lambda表达式的参数列表
* 右: lambda表达式所需执行的功能,lambda体
* 语法格式一:
* 接口中的方法:无参数、无返回值
* 函数式接口名 变量名 = () -> System.out.println("Hello Lambda");
* 语法格式二:
* 接口中的方法:有一个参数、无返回值
* 函数式接口名 变量名 =(x) -> System.out.println(x);
* 语法格式三:
* 接口中的方法:如果只有一个参数小括号可以省略不写、无返回值
* 函数式接口名 变量名 = x -> System.out.println(x);
* 语法格式四:
* 接口中的方法:有多个参数、有返回值 、多条语句
* Comparator<Integer> comparator=(x,y)->{
* System.out.println("函数式接口");
* return Integer.compare(x,y);
* };
* 语法格式五:
* 接口中的方法:有多个参数、有返回值 、只有条语句大括号可以省略、return 可以省略
* Comparator<Integer> comparator=(x,y)->Integer.compare(x,y);
* 语法格式六:
* 参数列表的数据类型可以省略不写,java JVM编译器可通过上下文推断出数据类型
*/
public class Testlambda2 {
/**
* 语法格式一:参数、无返回值
*/
@Test
public void test01(){
//jdk1.7 必须加 final 修饰
int num=0;
Runnable hello_lambda = new Runnable() {
@Override
public void run() {
System.out.println("hello Lambda"+num);
}
};
hello_lambda.run();
System.out.println("--------------------------");
Runnable hello_lambda2= () -> System.out.println("Hello Lambda");
hello_lambda2.run();
}
/**
* 语法格式二:有一个参数、无返回值
*/
@Test
public void test02(){
Consumer com =(x) -> System.out.println(x);
com.accept("666");
}
/**
* 语法格式三:只有一个参数小括号可以省略不写、无返回值
*/
@Test
public void test03(){
Consumer com =x -> System.out.println(x);
com.accept("666");
}
/**
* 语法格式四:有多个参数、有返回值 多条语句
*/
@Test
public void test04(){
Comparator<Integer> comparator=(x,y)->{
System.out.println("函数式接口");
return Integer.compare(x,y);
};
}
/**
* 语法格式五:有多个参数、有返回值 、只有条语句大括号可以省略、return 可以省略
*/
@Test
public void test05(){
Comparator<Integer> comparator=(x,y)->Integer.compare(x,y);
}
/**
* 语法格式六 参数类型可以通过上下文自动推断
*/
@Test
public void test06(){
// <Integer> 没有他就会报错
Comparator<Integer> comparator=( x, y)->Integer.compare(x,y);
String [] strs={"aaa","bbb" };
String [] strs2;
//会报错strs2={"aaa","bbb" };
//<Object> 没有他会报错
ArrayList<Object> objects = new ArrayList<>();
//jdk 1.8 不需要写他根据目标方法的类型可以推断
show(new HashMap<>());
}
public void show(Map<String,Integer> map){}
@Test
public void test07(){
}
}
lambda表达式练习
pojo
public class Employee {
// 名字
private String name;
// 年龄
private Integer age;
//薪资
private double salary;
略 get and set 空参 有参构造 toString
}
1.调用 Collections.sort()方法,通过定制排序比较两个Employee(先按照年龄比,年龄相同,按姓名比),使用lambda最为参数传递
/**
* 数据集合
*/
List<Employee> employees = Arrays.asList(
new Employee("张三",36,8899.99),
new Employee("李四",25,4499.99),
new Employee("王五",15,5599.99),
new Employee("赵六",35,3399.99),
new Employee("天气",5,2299.99)
);
@Test
public void test1(){
Collections.sort(employees,(e1,e2)->{
if(e1.getAge().equals(e2.getAge())){
return e1.getName().compareTo(e2.getName());
}else{
return Integer.compare(e1.getAge(),e2.getAge());
}
});
employees.forEach(employee -> System.out.println(employee));
}
2.声名函数式接口,接口中声明方法 public String getValue(String str)将一个字符串转换成大写并作为方法返回值
@FunctionalInterface
public interface GetStringValue {
String getStringValue(String str);
}
@Test
public void test2(){
System.out.println(getValue("aaa", (str) -> str.toUpperCase()));
}
public String getValue(String str, GetStringValue getStringValue){
return getStringValue.getStringValue(str);
}
3.声明一个带两个泛型的函数式接口,泛型类型为<T,R> T为参数 R为返回值 ,计算两个Long型参数的和,再计算两个Long型参数类型的乘机
接口
@FunctionalInterface
public interface LambdaSumDemo<T,R> {
R sum(T t,R r);
}
@Test
public void test3(){
System.out.println(operation(3L, 4L, (l1, l2) -> l1 + l2));
System.out.println(operation(3L, 4L, (l1, l2) -> l1 * l2));
}
/**
* 对于两个Long类型数据处理
* @param l1
* @param l2
* @param lambdaSumDemo
*/
public Long operation(Long l1, Long l2, LambdaSumDemo<Long,Long> lambdaSumDemo){
return lambdaSumDemo.sum(l1, l2);
}
Function系列
@FunctionalInterface
public interface Function<T, R> {
// 接收一个参数T,返回一个结果R
R apply(T t);
}
Function代表的是有参数,有返回值的函数。还有很多类似的Function接口:
接口名 | 描述 |
---|---|
BiFunction<T,U,R> | 接收两个T和U类型的参数,并且返回R类型结果的函数 |
DoubleFunction<R> | 接收double类型参数,并且返回R类型结果的函数 |
IntFunction<R> | 接收int类型参数,并且返回R类型结果的函数 |
LongFunction<R> | 接收long类型参数,并且返回R类型结果的函数 |
ToDoubleFunction<T> | 接收T类型参数,并且返回double类型结果 |
ToIntFunction<T> | 接收T类型参数,并且返回int类型结果 |
ToLongFunction<T> | 接收T类型参数,并且返回long类型结果 |
DoubleToIntFunction | 接收double类型参数,返回int类型结果 |
DoubleToLongFunction | 接收double类型参数,返回long类型结果 |
要么明确了参数不确定返回结果,要么明确结果不知道参数类型,要么两者都知道。
/**
* 函数型接口 Function<T,R>
*/
@Test
public void test04() {
String asdada = getStr("asdada", (x) -> {
return x.toUpperCase();
});
System.out.println("大写:"+asdada);
//只有一个参数,方法体内只有一条语句 小括号 return 大括号可以省略
String asdada2 = getStr(asdada, x -> x.toLowerCase());
System.out.println("小写:"+asdada2);
}
/**
* 用于处理字符串
*/
public String getStr(String s, Function<String, String> function) {
return function.apply(s);
}
Consumer系列
@FunctionalInterface
public interface Consumer<T> {
// 接收T类型参数,不返回结果
void accept(T t);
}
Consumer系列与Function系列一样,有各种衍生接口,这里不一一列出了。不过都具备类似的特征:那就是不返回任何结果。
/**
* Consumer 消费型接口
*/
@Test
public void test01(){
happy(1000.0,(x)->{
System.out.println("工资:" + x + "元");
});
}
public void happy(double money, Consumer<Double> con){
con.accept(money);
}
Predicate系列
@FunctionalInterface
public interface Predicate<T> {
// 接收T类型参数,返回boolean类型结果
boolean test(T t);
}
Predicate系列参数不固定,但是返回的一定是boolean类型。
/**
* Predicate 断言
*/
@Test
public void test05(){
List<String> strings = Arrays.asList("百度", "腾讯->过滤", "阿里", "京东->过滤");
List<String> strings1 = filterStr(strings, x -> x.length() > 3);
System.out.println(strings1);
}
/**
* 将满足条件的字符串,放入集合中
* @param list 传入需要过滤的字符串集合
* @param stringPredicate
* @return
*/
public List<String> filterStr(List<String> list, Predicate<String> stringPredicate){
ArrayList<String> strings = new ArrayList<>();
for (String string : list) {
if(stringPredicate.test(string)){
strings.add(string);
}
}
return strings;
}
Supplier系列
@FunctionalInterface
public interface Supplier<T> {
// 无需参数,返回一个T类型结果
T get();
}
Supplier系列,英文翻译就是“供应者”,顾名思义:只产出,不收取。所以不接受任何参数,返回T类型结果。
/**
* 供给型对象产生一些对象
*/
@Test
public void test02(){
List<Integer> numList = getNumList(3, () -> (int) (Math.random() * 100));
System.out.println(numList);
}
/**
* 产生制定个数的整数一些数放入集合中
* @param num 数组的长度
* @param supplier 供给型接口
* @return
*/
public List<Integer> getNumList(int num, Supplier<Integer> supplier) {
List<Integer> objects = new ArrayList<>();
for (int i=0;i<num;i++){
// 生成的随机数
Integer integer = supplier.get();
objects.add(integer);
}
return objects;
}
方法引用
package cn.bufanli.lambda;
import cn.bufanli.pojo.Employee;
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* @author BuShuangLi
* @date 2019/3/11
* 方法引用: 若lambda 体中的内容有方法已经实现了,我们可以使用"方法引用"
* (可以理解为方法引用是lambda 表达式的另一种表现形式)
* 主要有三种语法格式:
*
* 对象::实例方法名
*
* 类::静态方法名
*
* 类::实例方法名(非静态方法)
* 注意:
* ①: lambda体中的参数列表和返回值与引用的函数式接口方法参数列表和返回值一致
* ②: 第一个参数是实例方法的调用者,第二个参数这是实例方法的参数时可以使用 类::实例方法名
*/
public class Testlambda5 {
/**
* 类::实例方法名
*/
@Test
public void test03(){
BiPredicate<String,String> biPredicate =(x,y)->x.equals(y);
//第一个参数是实例方法的调用者,第二个参数这是实例方法的参数时
BiPredicate<String,String> biPredicate2 =String::equals;
}
/**
* 类::静态方法名
*/
@Test
public void test02(){
Comparator<Integer> com=(x,y)->Integer.compare(x,y);
Comparator<Integer> com2=Integer::compare;
}
/**
* 对象::实例方法名
*/
@Test
public void test01(){
//1
Consumer<String> con = x -> System.out.println(x);
//可以用方法引用 lambda体中的参数列表和返回值与引用的方法返回值和参数列表一致
PrintStream ps =System.out;
//2
Consumer<String> s= ps::println;
//3
Consumer<String> s2= System.out::println;
s2.accept("阿达");
Employee employee = new Employee();
employee.setName("测试");
Supplier<String> sp=employee::getName;
System.out.println(sp.get());
}
}
构造器引用
package cn.bufanli.lambda;
import cn.bufanli.pojo.Employee;
import org.junit.Test;
import java.util.function.Supplier;
/**
* @author BuShuangLi
* @date 2019/3/11
* 构造器引用
* 格式:
* ClassName::new
* 需要调用的构造器的参数列表要与函数式接口中抽象的方法参数列表保持一致
*/
public class Testlambda6 {
@Test
public void test01(){
Supplier<Employee> supplier=()->new Employee();
Employee employee = supplier.get();
//构造器引用
Supplier<Employee> supplier2=Employee::new;
Employee employee1 = supplier2.get();
}
}
数组引用
package cn.bufanli.lambda;
import org.junit.Test;
import java.util.function.Function;
/**
* @author BuShuangLi
* @date 2019/3/11
* 数组引用
* Type[]::new;
*
*/
public class Testlambda7 {
@Test
public void test01(){
Function<Integer,String[]> fun=x -> new String[x];
String[] apply = fun.apply(10);
System.out.println(apply.length);
Function<Integer,Integer[]> fun2=Integer[]::new;
Integer[] apply1 = fun2.apply(10);
System.out.println(apply1.length);
}
}