0
点赞
收藏
分享

微信扫一扫

Java8函数式接口编程【lambda表达式、FunctionalInterface注解、Supplier、Consumer、Predicate、Function函数式接口】


  • ​​1、函数式接口的定义​​
  • ​​2、FunctionalInterface注解​​
  • ​​3、函数式接口的使用​​
  • ​​4、lambda延迟执行特性​​
  • ​​5、Supplier函数式接口​​
  • ​​6、Consumer函数式接口​​
  • ​​7、Predicate函数式接口​​
  • ​​8、Function函数式接口​​

1、函数式接口的定义

有且仅有一个抽象方法的接口

函数式接口顾名思义就是函数式编程的接口,在Java中最能体现函数式编程的无非就是Lambda,所以函数式接口是可以适用于Lambda使用的接口;

只有确保只有一个抽象方法,Lambda才能顺利地推导

2、FunctionalInterface注解

该注解与Override注解类似,FunctionalInterface用来检测该接口是否是一个函数式接口(只有一个抽象方法)

被@FunctionalInterface注解标记的类型表明这是一个函数接口。从概念上讲,函数接口只有一个抽象方法。如果接口声明的抽象方法覆写Object类的公共方法,那这方法不算作接口的抽象方法,因为接口具有Object方法的默认实现。

3、函数式接口的使用

首先定义一个函数式接口

@FunctionalInterface
public interface MyFunctionInterface {
public abstract void method();
}

(1)第一种使用方式(实现接口)

重写接口
在testFun方法参数中定义接口
调用时传入它的实现类

public class MyFunctionInterfaceImpl implements MyFunctionInterface{
@Override
public void method() {
System.out.println("第一种函数式接口的使用方式...");
}
}

public class TestFunctionInterface {

public static void testFun(MyFunctionInterface myFunctionInterface) {
myFunctionInterface.method();
}
public static void main(String[] args) {
testFun(new MyFunctionInterfaceImpl());
}
}

(2)内名内部类

testFun(new MyFunctionInterface() {
@Override
public void method() {
System.out.println("第二种实现方式...");
}
});

(3)Lambda表达式

testFun(()->{
System.out.println("第三种实现方式");
});
或者
testFun(()-> System.out.println("第三种实现方式"));



4、lambda延迟执行特性

使用一个日志案例来演示

public class lambdaLater {

public static void log(int k, String msg) {
if (k == 1) {
System.out.println(msg);
}
}

public static void main(String[] args) {
String msg1 = "aa";
String msg2 = "bb";
String msg3 = "cc";

log(2, msg1 + msg2 + msg3);
}
}

根据上文代码,如果传入的k=2,那么日志不会打印,但是msg1 + msg2 + msg3已经完成了拼接,这样就会浪费性能。

❤️ 经过lambda优化

使用lambda之前,首先需要定义一个函数式接口。

@FunctionalInterface
public interface LambdaLaterInterface {
public abstract String printMsg();
}

测试

public class lambdaLater {

public static void log2(int k, LambdaLaterInterface lambdaLaterInterface) {
if (k == 1) {
System.out.println(lambdaLaterInterface.printMsg());
}
}

public static void main(String[] args) {
String msg1 = "aa";
String msg2 = "bb";
String msg3 = "cc";

log2(2, () -> {
System.out.println("------");
return msg1 + msg2 + msg3;
});
}
}

结果如下



5、Supplier函数式接口

@FunctionalInterface
public interface Supplier<T> {

/**
* Gets a result.
*
* @return a result
*/
T get();
}

根据Supplier源代码可以看出,Supplier接口中是一个无参的的抽象方法;当你接口泛型指定什么类型,那么T get()抽象方法就会返回什么类型。

所以Supplier被成为生产型接口

public class SupplierDemo {

public static String sup(Supplier<String> supplier) {
return supplier.get();
}

public static void main(String[] args) {
//只有一行代码,省略了return和{}和,
String s = sup(() -> "hello");
System.out.println(s);
}
}

public class SupplierDemo {

public static int getMax(Supplier<Integer> sup) {
return sup.get();
}
public static void main(String[] args) {
int[] nums = {1, 3, 5, 0, 9};
int maxNum = getMax(() -> {
int max = nums[0];
for (int temp : nums) {
if (temp > max)
max = temp;
}
return max;
});
System.out.println(maxNum);
}
}



6、Consumer函数式接口

@FunctionalInterface
public interface Consumer<T> {

/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);

default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

这个Consumer接口刚好和Supplier接口的作用相反,如果接口泛型定义了什么类型,那么方法accept就可以消费什么类型;

Consumer是一个典型的消费型接口

public class ConsumerDemo {
public static void strRev(String str, Consumer<String> con) {
con.accept(str);
}
public static void main(String[] args) {
strRev("test", (temp) -> {
String result = new StringBuilder(temp).reverse().toString(); //反转字符串
System.out.println(result);
});
}
}

在Consumer接口中,有一个默认的方法andThen

这个andThen方法的作用是对两个Consumer接口进行连接消费

default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}

public class ConsumerDemo {

public static void strRev(String str, Consumer<String> consumer, Consumer<String> consumer2) {
consumer.andThen(consumer2).accept(str);
}
//进行组合消费
strRev("hello",
(name) -> {
System.out.println(name.toLowerCase());
},
(name2) -> {
System.out.println(name2.toUpperCase());
});
}
}



7、Predicate函数式接口

源代码中包含了一个抽象方法test和四个默认方法

@FunctionalInterface
public interface Predicate<T> {

/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t); //抽象方法
//逻辑与
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
//逻辑否
default Predicate<T> negate() {
return (t) -> !test(t);
}
//逻辑或
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}

//比较两个对象是否相等
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}

public class PredicateDemo {

public static boolean predicate(int a, Predicate<Integer> predicate) {
return predicate.test(a);
}
public static void main(String[] args) {

boolean flag = predicate(6, (num) -> {
return num > 5;
});
System.out.println(flag);
}
}

and方法的用法,与&&等同

public class PredicateDemo {

public static boolean predicate2(int a, Predicate<Integer> pre, Predicate<Integer> pre2) {
return pre.and(pre2).test(a);
}

public static void main(String[] args) {
boolean flag2 = predicate2(6,
(num) -> {
return num > 2;
},
(num2) -> {
return num2 > 8;
});
System.out.println(flag2);
}
}

or方法和and方法类似,与||等同。
negate方法,与!(取反)等同。



8、Function函数式接口

andThen方法的应用

在fun的基础上,fun2在进行加20,结果等于42;

public static Integer function2(String s, Function<String, Integer> fun, Function<Integer,Integer> fun2) {
return fun.andThen(fun2).apply(s);
}
public static void main(String[] args) {
Integer a = function2("12", (num) -> {
return Integer.valueOf(num) + 10;
}, (num)->{
return num + 20;
});
System.out.println(a);
}


举报

相关推荐

0 条评论