目录
函数式接口
注解
注释是给程序员看的,而注解会编译进JVM,比如@Override重写,如果重写的时候不加该注解,JVM将不会认为这是重写的。
@FunctionalInterface
函数式接口,必须要一个接口并且只包含一个抽象方法才能使用该注解,一般配合lambda表达式使用
四个常用的函数式接口
Supplier
- 生产者接口,用来生产对象,T get()方法
public class Demo {
public static void main(String[] args) {
int number = 10;
System.out.println(lambda(()->number*2));
}
public static int lambda(Supplier<Integer> s){
return s.get();
}
}
Consumer
- 消费者接口,使用一个对象,void accept(T var1)方法
public class Demo {
public static void main(String[] args) {
int number = 10;
lambda((t) -> System.out.println(t*2),number);
}
public static void lambda(Consumer<Integer> con,int n) {
con.accept(n);
}
}
- Consumer<T> andThen(Consumer<? super T> after)方法
public class Demo {
public static void main(String[] args) {
Integer number = 10;
lambda(t -> System.out.println(t+1),t->System.out.println(t*2),number);
}
public static void lambda(Consumer<Integer> con1,Consumer<Integer> con2,int n) {
con1.andThen(con2).accept(n);
//等价于以下代码
// con1.accept(n);
// con2.accept(n);
}
}
Predicate
- 用于判断,boolean Test(T t)方法
public class Demo {
public static void main(String[] args) {
Integer number = 10;
int[] arr = {1,4,5,3,7,3,5,3,6};
lambda(n->n>3,arr);
}
public static void lambda(Predicate<Integer> pre,int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (pre.test(arr[i])) System.out.println(arr[i]);
}
}
}
- Predicate<T> and(Predicate<? super T> other)方法
public class Demo {
public static void main(String[] args) {
Integer number = 10;
int[] arr = {1,4,5,3,7,3,5,3,6};
lambda(n->n>3,n->n<8,arr);
}
public static void lambda(Predicate<Integer> pre1,Predicate<Integer> pre2,int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (pre1.and(pre2).test(arr[i])) System.out.println(arr[i]);
//等价于以下代码
// if (pre1.test(arr[i])&& pre2.test(arr[i])) System.out.println(arr[i]);
}
}
}
- Predicate<T> negate()方法
public class Demo {
public static void main(String[] args) {
Integer number = 10;
System.out.println(lambda(n->n>5,number));
}
public static boolean lambda(Predicate <Integer> pre,Integer number) {
return pre.negate().test(number);
//等价于以下代码
// return !pre.test(number);
}
}
Function
- 用于格式转化,R apply(T t)方法
public class Demo {
public static void main(String[] args) {
Integer number = 10;
System.out.println(lambda(n->Integer.toString(n),number).getClass());
}
public static String lambda(Function<Integer,String> fun,Integer i) {
return fun.apply(i);
}
}
- <V> Function<T,V> andThen(Function<? super R,? extends V> after) 方法
public class Demo {
public static void main(String[] args) {
Integer number = 10;
System.out.println(lambda(i->Integer.toString(i),s->s.getBytes(),number).getClass());
}
public static byte[] lambda(Function<Integer,String> fun1,Function<String,byte[]> fun2,Integer i) {
return fun1.andThen(fun2).apply(i);
//等价于以下代码
// return fun2.apply(fun1.apply(i));
}
}
Stream流
Stream(I)用来操作集合的流,类似于工程的流水线
获得Stream流的方式
- List获得Stream对象
List<String> list = List.of("aaa","bbb","ccc");//快速生成一个不可变的集合对象 Stream<String> stream = list.stream()
- Set获得Stream对象
Set<String> set = Set.of("aaa","bbb","ccc"); Stream<String> stream = set.stream();
- Map获得Stream对象
Map<String,Integer> map = Map.of("aaa",1,"bbb",2,"ccc",3); Stream<String> stream = map.keySet().stream(); Stream<Integer> stream2 = map.values().stream(); Stream<Map.Entry<String,Integer>> stream3 = map.entry().stream();
- 数组获得Stream对象
String[] arr = {"aaa","bbb","ccc"}; Stream<String> stream = Arrays.stream(arr);
- 直接将很多元素包装成Strean
Stream<Integer> stream = Stream.of(5,3,8,3);
常用API
延迟方法:返回值还是Stream流
终结方法:返回值不是Stream流
返回值 | 方法 | 描述 |
void | forEach(Consumer<? extends T> action) | 对此流的每个元素进行遍历操作 |
Stream<T> | filter(Predicate<? super T> predicate) | 返回按条件筛选过后的流 |
<R> Stream<R> | map(Function<? super T,? extends R> mapper) | 返回将此流装换成另一个类型的流 |
Stream<T> | limit(long maxSize) | 返回取前maxSize个元素的流 |
Stream<T> | skip(long n) | 返回跳过(丢弃)n个元素的流 |
long | count() | 返回流中元素的数量 |
static<T> Stream<T> | concat(Stream<? extends T> a,Stream<? extends T> b) | 返回一个a流拼接b流的流(a在前b在后) |
Object[] | toArray() | 返回包含此流中所有元素的数组 |
public static void main(String[] args) {
List<String> list = List.of("a","bb","ccc","dddd","eeeee","ffffff");//快速生成一个不可变的集合对象
Stream<String> stream = list.stream();
//先筛选长度大于1的,再根据长度转化成Integer类型,再跳过一个,再取前三个,再遍历输出
stream.filter(n->n.length()>1).map(n->n.length()).skip(1).limit(3).forEach(n-> System.out.println(n));
}
特殊的lambda表达式的简化语法
使用前提
- 必须是lambda表达式
- lambda表达式中只有一句代码
- 在lambda表达式的方法参数,直接传递给lambda表达式内调用方法的参数
使用方法
对象引用普通成员方法
对象::成员方法
n -> System.out.println(n) 可以简化成 System.out::println
class Koo{
void printKoo( Object o){
System.out.println(o);
}
}
interface printFun{
void print(Object o);
}
public class Demo {
static void printMain(printFun pf,Object o){
System.out.println("---------------");
pf.print(o);
}
public static void main(String[] args) {
Koo koo = new Koo();
printMain(koo::printKoo,"aaaaa");
// 等价于以下代码
printMain(n->koo.printKoo(n),"aaaaa");
// 等价于以下代码
printMain(new printFun() {
@Override
public void print(Object o) {
koo.printKoo(o);
}
}, "aaaaa");
}
}
类引用静态方法
类::静态方法
n -> Math.abs(n) 可以简化成 Math::abs
class Koo{
static void printKoo( Object o){
System.out.println(o);
}
}
interface printFun{
void print(Object o);
}
public class Demo {
static void printMain(printFun pf,Object o){
System.out.println("---------------");
pf.print(o);
}
public static void main(String[] args) {
printMain(Koo::printKoo, "aaaaa");
//等价于以下代码
printMain((n)->Koo.printKoo(n),"aaaaa");
//等价于以下代码
printMain(new printFun() {
@Override
public void print(Object o) {
Koo.printKoo(o);
}
},"aaaaa");
}
}
引用构造方法
类::new
n -> new String(n) 可以简化成 String::new
class Koo{
Integer i;
public Koo(Integer i) {
this.i = i;
}
}
interface creatFun{
Koo create(Integer i);
}
public class Demo {
public static void creatKoo(creatFun cre,Integer i){
System.out.println(cre.create(i));
}
public static void main(String[] args) {
creatKoo(Koo::new,10);
//等价于以下代码
creatKoo((i)-> new Koo(i),10);
//等价于以下代码
creatKoo(new creatFun() {
@Override
public Koo create(Integer i) {
return new Koo(i);
}
},10);
}
}
引用数组的构造器
数组类型::new
(n) -> new int[n] 可以简化成 int[]::new
interface creatFun{
int[] create(int len);
}
public class Demo {
public static void creat(creatFun cre,int i){
System.out.println(Arrays.toString(cre.create(i)));
}
public static void main(String[] args) {
creat(int[]::new,10);
//等价于以下代码
creat(n -> new int[n],10);
//等价于以下代码
creat(new creatFun() {
@Override
public int[] create(int len) {
return new int[len];
}
},10);
}
}
通过this引用成员方法
this::方法
n -> this.method(n) 可以简化成 this::method
class Koo{
void method1(){
method2(this::method3,10);
//等价于以下代码
method2(i -> this.method3(i),10);
//等价于以下代码
method2(new creatFun() {
@Override
public void creat(int i) {
new Koo.method3(i);
}
}, 10);
}
void method2(creatFun cre,int i){
cre.creat(i);
}
void method3(int i){
System.out.println(i+1);
}
}
interface creatFun{
void creat(int i);
}
public class Demo {
public static void main(String[] args) {
Koo koo = new Koo();
koo.method1();
}
}
通过super引用父类成员方法
super::方法
n -> this.method(n) 可以简化成 super::method
class Poo{
void method3(int i){
System.out.println(i+2);
}
}
class Koo extends Poo{
void method1(){
method2(super::method3,10);
//等价于以下代码
method2(i -> super.method3(i),10);
//等价于以下代码
method2(new creatFun() {
@Override
public void creat(int i) {
new Poo().method3(i);
}
}, 10);
}
void method2(creatFun cre,int i){
cre.creat(i);
}
void method3(int i){
System.out.println(i+1);
}
}
interface creatFun{
void creat(int i);
}
public class Demo {
public static void main(String[] args) {
Koo koo = new Koo();
koo.method1();
}
}
总结
- 四个常用的函数式接口,起码要了解他们当中的抽象方法
- Stream流可以快速对集合进行一些操作,节省代码量
- 特殊的lambda表达式简化方法有六种,可以不用,但是必须要看得懂