Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。
本质上是一段匿名内部类,也可以是一段可以传递的代码。
还有叫箭头函数的…
闭包就是能够读取其他函数内部变量的函数,比如在java中,方法内部的局部变量只能在方法内部使用,所以闭包可以理解为定义在一个函数内部的函数
闭包的本质就是将函数内部和函数外部链接起来的桥梁
允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
列表迭代
Map映射
Reduce聚合
代替一个不想命名的函数或是类,该函数或类往往并不复杂。
想尽量缩短代码量的各个场景均可以
1、(parameters) -> expression
2、(parameters) ->{ statements; }
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值
如果只有一条语句,并且是返回值语句,就可以不写return 不写 {}
如果写上{} 就必须写return 和 ;
如果有 多条语句,必须写{} return 和 ; 也必须写
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2*x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
//1.简单使用lambda表达式进行遍历
String[] array = {"abc","cab","bca"};
List list = Arrays.asList(array);
list.forEach(x->System.out.println(x));
//2.给集合排序
list.sort((x,y)->x.compareTo(y));
list.forEach(x->System.out.println(x));
英文称为Functional Interface
其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。
其可以被隐式转换为 lambda 表达式。
函数式接口是仅制定一个抽象方法的接口
可以包含一个或多个静态或默认方法
专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用
pa
ckage homework;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
*
* @author Antg
* @date 2021年7月5日
* @Description
* lambda表达式的练习
*/
public class Hw01 {
public static void main(String[] args) {
//3.函数式接口(无参)
//3.1第一种调用方式
call(()->{System.out.println("这个是一个回调函数");});
//3.2第二种调用方式
FuncInterfaceNoParam func = ()->{System.out.println("这个是一个回调函数2");};
func.callback();
//4.函数式接口(有参)
callWithParam((String name)->{System.out.println("有参的函数式接口,参数:"+name);},"张三");
}
//定义一个静态方法,接收函数式接口(无参)
public static void call(FuncInterfaceNoParam func){
func.callback();
}
//定义一个静态方法,接收函数式接口(有参)
public static void callWithParam(FuncInterfaceHavingParam func,String name){
func.callback(name);
}
}
package homework;
public interface FuncInterfaceHavingParam {
public void callback(String name);
}
package homework;
//无参函数式接口
/*
* 函数式接口只能有一个抽象方法,但是可以有多个非抽象方法
* */
@FunctionalInterface
public interface FuncInterfaceNoParam {
//这是一个回调函数
public void callback();
}
Supplier
有一个get方法,用于获取数据
Consumer
有一个accept(T)方法,用于执行消费操作,可以对给定的参数T 做任意操作
Function
顾名思义,是函数操作的
有一个R apply(T)方法,Function中没有具体的操作,具体的操作需要我们去为它指定,因此apply具体返回的结果取决于传入的lambda表达式
Predicate
就是做一些判断,返回值为boolean
有一个boolean test(T)方法,用于校验传入数据是否符合判断条件,返回boolean类型
package homework;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
*
* @author Antg
* @date 2021年7月5日
* @Description
* lambda表达式的练习
*/
public class Hw01 {
public static void main(String[] args) {
//5.jdk自带的函数式接口
//5.1 Supplier
System.out.println(call(()->"Supplier接口可以用来获取值"));
//5.2 Consumer
call(()->{System.out.println("Consumer接口可以用来处理传入的数据");});
//5.3 Function
System.out.println("Function接口的函数,将String类型转换成int类型:"+call((String param)->{return Integer.valueOf(param);},"123"));
//5.4 Predicate 断言接口
call((p)->{return p==1;},1);
}
//Supplier接口
public static String call(Supplier func){
return func.get();
}
//Comsumer接口
public static void call(Consumer func,String param){
func.accept(param);
}
//Function接口
public static Integer call(Function func,String param){
return func.apply(param);
}
//Predicate接口
public static void call(Predicate func,Integer param){
if(func.test(param)){
System.out.println("条件符合要执行的操作");
}else{
System.out.println("条件不符合要执行的操作");
}
}
}
Lambda表达式的另外一种表现形式,提高方法复用率和灵活性。
更简单、代码量更少、复用性、扩展性更高。
package homework;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
*
* @author Antg
* @date 2021年7月5日
* @Description
* lambda表达式的练习
*/
public class Hw01 {
public static void main(String[] args) {
//6.方法引用
//常规lambda写法
Supplier sup = () -> new Integer(123456).toString();
System.out.println("普通lambda写法"+sup.get());
//使用方法引用
//对象的引用 :: 实例方法名
Supplier sup2 = new Integer(123456)::toString;
System.out.println("方法引用1"+sup2);
//类名 :: 静态方法名
BiFunction bif = Integer::max;
System.out.println("方法引用2"+bif.apply(10, 11));
//类名 :: 实例方法名
BiPredicate bp = String::equals;
System.out.println("方法引用3"+bp.test("aaa", "bbb"));
//7.构造器调用
//普通lambda写法
Supplier
数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,流讲的是计算
即一组用来处理数组,集合的API。
Stream 不是数据结构,没有内部存储,自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
不支持索引访问。
延迟计算
支持并行
很容易生成数据或集合
支持过滤,查找,转换,汇总,聚合等操作。
流式计算处理,需要延迟计算、更方便的并行计算
更灵活、简洁的集合处理方式场景
Stream分为源source,中间操作,终止操作。
流的源可以是一个数组,集合,生成器方法,I/O通道等等。
一个流可以有零个或多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用,一个流只会有一个终止操作。
中间操作也称为转换算子-transformation
Stream只有遇到终止操作,它的数据源会开始执行遍历操作。
终止操作也称为动作算子-action
因为动作算子的返回值不再是 stream,所以这个计算就终止了
只有碰到动作算子的时候,才会真正的计算
//1.通过数组的Stream.of()方法
String[] strArray = {"one","two","three","four"};
Stream stream1 = Stream.of(strArray);
//2.通过集合
List list1 = Arrays.asList(strArray);
Stream stream2 = list1.stream();
//3.通过Stream.generate方法来创建
Stream stream3 = Stream.generate(()->1);
stream3.limit(10).forEach(x->System.out.println(x));
//4.通过iterate
Stream stream4 = Stream.iterate(1, x->x+2);
stream4.limit(5).forEach(x->System.out.println(x));
//5.已有类的stream源生成API
String str2 = "123456";
IntStream chars = str2.chars();
chars.forEach(x->System.out.println(x));
常用转换算子 filter,distinct,map,limit,skip,flatMap等
filter : 对元素进行过滤筛选,不符合的就不要了
distinct : 去掉重复的元素
skip : 跳过多少元素
limit : 取一个集合的前几条数据
map :
可以理解是在遍历集合的过程中,对元素进行操作,比如判断集合元素是否是a 返回boolean
因为 map的返回值,就是新集合中的元素,所以也可以在遍历的时候对集合的数据进行更改,比如都加 –
flatMap : 解决一个字符串数组 返回单一的字符串使用flatMap
本来集合中有两个数组,可以通过flatMap 把数组中的每一个元素都放到集合中,然后把数组去掉
注意只用此算子是不会真正进行计算的,只有后边调用动作算子才会真正计算。
循环 forEach
计算 min、max、count、average
匹配 anyMatch、allMatch、noneMatch、findFirst、findAny
汇聚 reduce
收集器 collect
1.8之前接口中只能定义public static final的变量和public abstract修饰的抽象方法。
1.8及以后版本,不仅兼容1.8以前的,并新增了默认方法定义和静态方法定义的功能。
即default方法和static方法。
让接口更灵活、更多变,更能够适应现实开发需要。
默认方法
可以被重写,也可以不重写。如果重写的话,就按实现类的方法来执行。
调用的时候必须是实例化对象调用。
静态方法
跟之前的普通类的静态方法大体相同
唯一不同的是不能通过接口的实现类的对象来调用,必须是类.静态方法的方式。
package homework;
/**
*
* @author Antg
* @date 2021年7月5日
* @Description
* 接口中的默认方法和静态方法
*/
public class Hw03 {
public static void main(String[] args) {
TestImpl testImpl = new TestImpl();
//接口的默认方法只能用实现类的实例来调用
testImpl.m1();
//接口的静态方法可以用接口名
TestInterface.m2();
}
public static interface TestInterface{
//默认方法
public default void m1(){
System.out.println("这里是接口的默认方法");
}
public static void m2(){
System.out.println("这里是静态方法");
}
}
//实现上述接口
public static class TestImpl implements TestInterface{
}
}