java基础篇笔记22

函数式接口在Java中是指:有且仅有一个抽象方法的接口
函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。
当然接口中可以包含其他方法(默认,私有,静态等)。

@FunctionalInterface注解
作用:可以检测接口是否是一个函数式接口
是:编译成功;
否:编译失败(接口中没有抽象方法或抽象方法的个数多于一个)。

使用Lambda表达式作为参数传递,仅仅是把参数传递到showlog方法中,只有满足条件才会进行操作,延迟操作可以做到性能优化。

Java中的Lambda表达式可以被当作是匿名内部类的替代品。如果方法的参数是一个函数
式接口类型,那么就可以使用Lambda表达式进行替代。使用Lambda表达式作为方法参数,其实就是使用函数式
接口作为方法参数。

例如 java.lang.Runnable 接口就是一个函数式接口,假设有一个 startThread 方法使用该接口作为参数,那么就
可以使用Lambda进行传参。这种情况其实和 Thread 类的构造方法参数为 Runnable 没有本质区别。

类似地,如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式。当需要通过一
个方法来获取一个 java.util.Comparator 接口类型的对象作为排序器时,就可以调该方法获取
其中直接return一个Lambda表达式即可。

常用函数式接口
java.util.function.Supplier 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对
象数据。
Supplier接口被称之为生产型接口,指定接口的反省是什么类型,那么接口中的get方法就会生产什么类型的数据。
java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,
其数据类型由泛型决定。
Consumer是一个消费型接口,繁星之星什么类型,就可以使用accept方法消费什么类型的数据,至于具体如何消费,需要自定义。

Consumer接口的默认方法andthen
作用:
需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费。
并且,两个接口哪个在前哪个就先消费。

java.util.function.Predicate 接口
作用:
对某种数据类型的数据进行判断,结果返回一个Boolean值

Predicate 接口中包含一个抽象方法:
boolean test(T t) :用来对指定数据类型进行判断的方法
结果:
符合条件,返回true
不符合条件,返回false

逻辑表达式: 与(&&),或(||),非(!)

Predicate 接口中有一个方法and,表示并且关系,也可以用于连接两个判断条件
default Predicate and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) ‐> test(t) && other.test(t);
}
方法内部的两个判断条件,也是使用&&运算符连接起来的。
类似的,接口中还有or和negate默认方法,可实现或和非
default Predicate or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) ‐> test(t) || other.test(t);
}

default Predicate negate() {
return (t) ‐> !test(t);
}

java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据。
前者称为前置条件,后者称为后置条件。
Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。
使用的场景例如:将 String 类型转换为 Integer 类型。
Function 接口中有一个默认的 andThen 方法,用来进行组合操作。

Stream(流)是一个来自数据源的元素队列
元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源流的来源。 可以是集合,数组 等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluentstyle)。
这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
内部迭代: 以前对集合遍历都是通过Iterator或者增强for的方式, 显式的在集合外部进行迭代, 这叫做外部迭
代。 Stream提供了内部迭代的方式,流可以直接调用遍历方法。

当使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source)→ 数据转换→执行操作获取想要的结
果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象。

java.util.stream.Stream 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
• 所有的 Collection 集合都可以通过 stream 默认方法获取流;
• Stream 接口的静态方法 of 可以获取数组对应的流。

java.util.Collection 接口中加入了default方法 stream 用来获取流,所以其所有实现类均可获取流
default stream stream()
Stream 接口中提供了静态方法of可以获取数组对应的流
static Stream of (T…values)
参数是一个可变参数。

在流模式的操作中主要有两种方法:
延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方
法均为延迟方法。)
终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调
用。本小节中,终结方法包括 count 和 forEach 方法。

Stream流中的常见方法foreach
void foreach(Consumer<? super T> action);
该方法接收一个Consumer接口函数,会将每一个六元素交给该函数进行处理
Consumer接口是一个消费型的函数接口,可以传递Lambda表达式,消费数据。
简单记:
foreach方法,用来遍历流中的数据
是一个终结方法,遍历之后就不能继续调用stream流中的其他方法。

Stream流中的常见方法filter
Stream filter(Predicate<? super T> predicate);
filter 方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤
Predicate中的抽象方法:
boolean test(T t);

Stream流属于管道流,只能被消费(使用)一次
调用完方法之后,数据就会流转到下一个Stream流上,所以前一个Stream流就不能调用方法了。

如果需要将流中的元素映射到另一个流中,可以使用map方法
Stream map(Function<? super T, ? extends R> mapper);
该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
Function中的抽象方法:
R apply(T t);

Stream流中的常见方法count
long count();
count方法是一个终结方法,返回值是一个long类型的证书
所以不能再继续调用Stream流中的其他方法。

Stream流中的常见方法limit
limit 方法可以对流进行截取,只取用前n个。
Stream limit(long maxSize);
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
limit方法是一个延迟方法,只是对刘中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream刘中的其他方法。

Stream流中的常见方法skip:用于跳过元素
如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流。
Stream skip(long n);

Stream流中的常见方法concat:用于把流组合在一起
如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :
static Stream concat(Stream<? extends T> a, Stream<? extends T> b)

方法引用
双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方
法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

通过对象名引用成员方法
使用前提是对象名是已经存在的,成员方法也是已经存在的,
就可以使用对象名在引用成员方法。

通过类名引用静态成员方法
类已经存在,静态成员方法也存在
就可以通过类名直接引用静态成员方法。

通过super引用成员方法
super是已经存在的,父类的成员方法夜市已经存在的。
所以可以直接使用super引用父类的成员方法。

通过this引用成员方法
this代表当前对象,如果需要引用的方法就是当前类中的成员方法,那么可以使用“this::成员方法”的格式来使用方
法引用。

类的构造器引用
由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::new 的格式表示。

数组的构造器引用
与类的构造器引用类似,使用 数据类型[ ]::new的格式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值