JavaSE-Lambda表达式&Stream流

day20_Lambda

一、昨日回顾

二、今日目标

三、知识点

1. Lambda表达式

1.1 介绍

Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。

本质上是一段匿名内部类,也可以是一段可以传递的代码。

还有叫箭头函数的...

1.2 特点

 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

 使用 Lambda 表达式可以使代码变的更加简洁紧凑。

1.3 应用场景

列表迭代

Map映射

Reduce聚合

代替一个不想命名的函数或是类,该函数或类往往并不复杂。

想尽量缩短代码量的各个场景均可以

1.4 代码实现
1.4.1 具体语法

1、(parameters) -> expression

2、(parameters) ->{ statements; }

1.4.2 语法特点

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值

 如果只有一条语句,并且是返回值语句,就可以不写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.4.3 集合遍历

演示示例:_01_Lambda.java

1.4.4 集合排序

演示示例:_01_Lambda.java

2. 函数式接口

2.1 介绍

一个接口中只有一份个抽象方法

英文称为Functional Interface

 

其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

 

核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。

 

其可以被隐式转换为 lambda 表达式。

 

2.2 特点

 

函数式接口是仅制定一个抽象方法的接口

 

可以包含一个或多个静态或默认方法

 

专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解

如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解

如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用

回调函数

简单来说就是回调函数,方法的参数是一个方法,在这个方法中对传递的方法进行调用

 

2.3 应用场景

想通过函数式编程,提高编程效率的各种场景均可。

 

2.4 代码实现
2.4.1 无参情况

演示示例:_01_FunInterface.java

2.4.2 有参情况

public class FunInterface_02 {
// 自定义静态方法,接收接口对象
public static void call(MyFunctionInter_02 func, String message) {
// 调用接口内的成员方法
func.printMessage(message);
}
public static void main(String[] args) {
// 调用需要传递的数据
String message = "有参函数式接口调用!!!";
// 第一种调用 : 直接调用自定义call方法,传入函数,并传入数据
FunInterface_02.call((str) -> {
System.out.println(str);
}, message);
// 第二种调用 : 先创建函数对象,类似于实现接口的内部类对象
MyFunctionInter_02 inter = (str) -> {
System.out.println(str);
};
// 调用这个实现的方法
inter.printMessage(message);
}
}
// 函数式接口
@FunctionalInterface
interface MyFunctionInter_02 {
void printMessage(String message);
}

 

演示示例:_02_FunInterface.java

2.5 JDK自带常用的函数式接口
2.5.1 Supplier<T>接口

Supplier<T>接口 代表结果供应商,所以有返回值,可以获取数据

有一个get方法,用于获取数据

演示示例:_03_JdkOwn_01.java

2.5.2 Consumer<T>接口

Consumer<T>接口 消费者接口所以不需要返回值

有一个accept(T)方法,用于执行消费操作,可以对给定的参数T 做任意操作

public class _04_JdkOwn_02 {
private static void consumeResult(Consumer<String> function, String message) {
function.accept(message);
}
public static void main(String[] args) {
// 传递的参数
String message = "消费一些内容!!!";
// 调用方法
consumeResult(result -> {
System.out.println(result);
}, message);
}
}

 

演示示例:_04_JdkOwn_02.java

2.5.3 Function<T,R>接口

Function<T,R>接口 表示接收一个参数并产生结果的函数

顾名思义,是函数操作的

有一个R apply(T)方法,Function中没有具体的操作,具体的操作需要我们去为它指定,因此apply具体返回的结果取决于传入的lambda表达式

演示示例:_05_JdkOwn_03.java

2.5.4 Predicate<T>接口

Predicate<T>接口 断言接口

就是做一些判断,返回值为boolean

有一个boolean test(T)方法,用于校验传入数据是否符合判断条件,返回boolean类型

演示示例:_06_JdkOwn_04.java

3.方法引用和构造器调用

3.1概念说明

Lambda表达式的另外一种表现形式,提高方法复用率和灵活性。

3.2 特点

更简单、代码量更少、复用性、扩展性更高。

3.3 应用场景

若Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用。

不需要再复写已有API的Lambda的实现。

3.4 代码实现
3.4.1 方法引用

方法引用-3种形式

3.4.1.1 对象的引用 :: 实例方法名

演示示例:_01_FunCall.java

3.4.1.2 类名 :: 静态方法名

演示示例:_02_FunCall.java

3.4.1.3 类名 :: 实例方法名

演示示例:_03_FunCall.java

3.4.3 构造器调用

演示示例:_04_ConstructorCall.java

3.4.4 数组调用

演示示例:_05_ArrayCall.java

4.Stream API

4.1 概念说明

 数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。

集合讲的是数据,流讲的是计算

即一组用来处理数组,集合的API。

4.2 特点

Stream 不是数据结构,没有内部存储,自己不会存储元素。

Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

很容易生成数据或集合

支持过滤,查找,转换,汇总,聚合等操作。

4.3 应用场景

流式计算处理,需要延迟计算、更方便的并行计算

更灵活、简洁的集合处理方式场景

4.4 代码实现
4.4.1 运行机制说明

Stream分为源source,中间操作,终止操作。

流的源可以是一个数组,集合,生成器方法,I/O通道等等。

一个流可以有零个或多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用,一个流只会有一个终止操作。

中间操作也称为转换算子-transformation

Stream只有遇到终止操作,它的数据源会开始执行遍历操作。

终止操作也称为动作算子-action

因为动作算子的返回值不再是 stream,所以这个计算就终止了

只有碰到动作算子的时候,才会真正的计算

4.4.2 代码实现

4.4.2.1 生成stream流的5种方式说明

public static void main(String[] args) {
// 1 通过数组,Stream.of()
String[] str = { "a", "b", "c" };
Stream<String> str1 = Stream.of(str);
// System.out.println(str1);
// 2 通过集合
List<String> strings = Arrays.asList("a", "b", "c");
Stream<String> stream = strings.stream();
System.out.println(stream);
// 3 通过Stream.generate方法来创建
// 这是一个无限流,通过这种方法创建在操作的时候最好加上limit进行限制
Stream<Integer> generate = Stream.generate(() -> 1);
generate.limit(10).forEach(x -> System.out.println(x));
// 4 通过Stream iterate
Stream<Integer> iterate = Stream.iterate(1, x -> x + 2);
iterate.limit(100).forEach(x -> System.out.println(x));
// 5 已有类的stream源生成API
String str2 = "123456";
IntStream chars = str2.chars();
chars.forEach(x -> System.out.println(x));
}

 

演示示例:_01_Stream.java

4.4.2.2 常用转换算子

 常用转换算子 filter,distinct,map,limit,skip,flatMap等

 

 filter : 对元素进行过滤筛选,不符合的就不要了

 

 distinct : 去掉重复的元素

 

 skip : 跳过多少元素

 

 limit : 取一个集合的前几条数据

 

 map : 可以理解是在遍历集合的过程中,对元素进行操作,比如判断集合元素是否是a 返回boolean

 因为map的返回值,就是新集合中的元素,所以也可以在遍历的时候对集合的数据进行更改,比如都加

 sorted :排序

 

 注意只用此算子是不会真正进行计算的,只有后边调用动作算子才会真正计算。

public static void main(String[] args) {
List<String> strings = Arrays.asList("a", "b", "c", "a");
Stream<String> stream = strings.stream();
/**
* 对元素进行过滤筛选,不符合的就不要了
*/
// collect 把符合条件的转换为集合strings,属于动作算子,因为不用动作算子这些转换算子不会执行,所以看不到结果
// 只要 a
List<String> value  = stream.filter(x -> x.equals("a")).collect(Collectors.toList());
// 集合中只有 a 了
System.out.println(value);

// 使用过之后,需要重新生成stream
stream = strings.stream();
/**
*  跳过1个元素 原来是 abca 现在就是 bca
*/
value = stream.skip(1).collect(Collectors.toList());
// bca
System.out.println(value);

/**
*  map : 可以理解是在遍历集合的过程中,对元素进行操作,比如判断集合元素是否是a 返回boolean
*    或者对集合元素进行更改数据,比如都加--
*/
stream = strings.stream();
// 判断集合元素,这样就是booelean 是a 就是true 否则就是false
List<Boolean> value1=stream.map(x -> x.equals("a")).collect(Collectors.toList());
// true,false,false,true
System.out.println(value1);

stream = strings.stream();
// 更改集合元素
value =stream.map(x -> x+"--").collect(Collectors.toList());
// a--, b--, c--, a--
System.out.println(value);
/**
* 去掉重复元素
*/
stream = strings.stream();
value = stream.distinct().collect(Collectors.toList());
// 去除一个a 只有a,b,c
System.out.println(value);
/**
* 取一个集合的前几条数据
*/
stream = strings.stream();
value = stream.limit(2).collect(Collectors.toList());
// ab
System.out.println(value);

/**
* 解决一个字符串数组  返回单一的字符串使用flatMap
*/
strings = Arrays.asList("1,2,3", "a,b,c");
stream = strings.stream();
// 本来集合中有两个数据 "1,2,3" 和 "a,b,c"
// 会把每一个元素 以 , 分割,得到字符串数组
// 然后把数组中每一个元素,都单独拿出来
        // 最终就会得到 1,2,3,a,b,c 6个元素 
// 通过 collect 把这6个元素 放到集合中
value =stream.map(x -> x.split(",")).flatMap(arr -> Arrays.stream(arr)).collect(Collectors.toList());
// 1, 2, 3, a, b, c
System.out.println(value);
}

 

演示示例:_02_Stream.java

4.4.2.3 常用动作算子

循环 forEach

计算 min、max、count、average

匹配 anyMatch、allMatch、noneMatch、findFirst、findAny

汇聚 reduce

收集器 collect

public static void main(String[] args) {
List<String> strings = Arrays.asList("a", "b", "c");
Stream<String> stream = strings.stream();
// 测试forEach
stream.filter(x -> x.equals("a")).forEach(x -> System.out.println(x));
// 测试count
stream = strings.stream();
long cnt = stream.count();
System.out.println(cnt);
// 测试collect
stream = strings.stream();
List<String> list = stream.map(x -> x + "--").collect(
Collectors.toList());
System.out.println(list);
}

 

演示示例:_03_Stream.java

5.接口中的默认方法和静态方法

5.1 概念说明

1.8之前接口中只能定义public static final的变量和public abstract修饰的抽象方法。

1.8及以后版本,不仅兼容1.8以前的,并新增了默认方法定义和静态方法定义的功能。

即default方法和static方法。

让接口更灵活、更多变,更能够适应现实开发需要。

5.2 特点

默认方法

可以被重写,也可以不重写。如果重写的话,就按实现类的方法来执行。

调用的时候必须是实例化对象调用。

静态方法

跟之前的普通类的静态方法大体相同

唯一不同的是不能通过接口的实现类的对象来调用,必须是类.静态方法的方式。

5.3 应用场景

默认方法

是为了解决之前版本接口升级导致的大批实现类的强制重写方法升级的问题。

涉及到接口升级的场景可以多用,从而提高了程序的扩展性、可维护性。

静态方法

跟默认方法为类似,也是为了解决接口升级的问题,默认方法解决了接口方法增加后其子类不必要全部重写的问题,静态方法解决了一次编写静态方法所有接口及其子类通用的问题,跟lambda表达式并用效果更加,进一步提高了程序扩展性和可维护性。

允许在已有的接口中添加静态方法,接口的静态方法属于接口本身,不被继承,也需要提供方法的静态实现后,子类才可以调用。

5.4 代码实现
5.4.1 默认方法

演示示例:_01_Interface.java

5.4.2 静态方法案例-1-一般情况

类名调用就行,各是各的,互不影响

演示示例:_02_Interface.java

5.4.3 静态方法案例-2-高级使用

类名调用就行,各是各的,互不影响

演示示例:_03_Interface.java

四、今日总结

见JavaSE1.8新特性总结

五、今日作业

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值